Primitive Type
Примитивный тип array
Массив фиксированного размера, обозначаемый как [T; N], где:
T— тип элементовN— неотрицательная константа времени компиляции (размер)
Синтаксис создания массивов
Существует два синтаксических способа создания массива:
- Список элементов:
[x, y, z] - Повторяющееся выражение:
[expr; N], гдеN— количество повторенийexprexprдолжно быть либо:- Значением типа, реализующего трейт
Copy - Константным значением
- Значением типа, реализующего трейт
Примечание: [expr; 0] разрешено и создаёт пустой массив. Однако expr всё равно будет вычислено, и результат будет немедленно удалён — учитывайте побочные эффекты.
Реализуемые трейты
Массивы любого размера реализуют следующие трейты (если это позволяет тип элементов):
| Трейт | Реализации |
|---|---|
Copy, Clone, Debug | Для всех массивов |
IntoIterator | Для [T; N], &[T; N] и &mut [T; N] |
PartialEq, PartialOrd, Eq, Ord | Для всех массивов |
Hash | Для всех массивов |
AsRef, AsMut | Для всех массивов |
Borrow, BorrowMut | Для всех массивов |
Особые реализации
- Default: Массивы размером от 0 до 32 (включительно) реализуют
Default, если тип элементов позволяет это. Реализации генерируются статически до размера 32. - From<Tuple>: Массивы размером от 1 до 12 (включительно) реализуют
From<Tuple>, гдеTuple— однородный кортеж соответствующей длины.
Приведение типов
Массивы приводятся к срезам ([T]), поэтому методы срезов можно вызывать на массивах. Большая часть API для работы с массивами предоставляется именно через срезы.
Важно: Срезы имеют динамический размер и не приводятся к массивам. Вместо этого используйте:
slice.try_into().unwrap()<ArrayType>::try_from(slice).unwrap()
Методы реализации
impl<T, const N: usize> [T; N]
| Метод | Версия | Описание |
|---|---|---|
map<F, U>(self, f: F) -> [U; N] | 1.55.0 | Применяет функцию к каждому элементу, возвращая массив того же размера |
try_map<F, R>(self, f: F) -> ... | nightly | Вариация map с обработкой ошибок |
as_slice(&self) -> &[T] | 1.57.0 (const) | Возвращает срез всего массива |
as_mut_slice(&mut self) -> &mut [T] | 1.57.0 (const) | Возвращает изменяемый срез всего массива |
each_ref(&self) -> [&T; N] | 1.77.0 (const) | Возвращает массив ссылок на элементы |
each_mut(&mut self) -> [&mut T; N] | 1.77.0 (const) | Возвращает массив изменяемых ссылок на элементы |
split_array_ref<const M>(&self) -> (&[T; M], &[T]) | nightly | Разделяет массив на две части по индексу M |
split_array_mut<const M>(&mut self) -> (&mut [T; M], &mut [T]) | nightly | Разделяет изменяемый массив на две части |
rsplit_array_ref<const M>(&self) -> (&[T], &[T; M]) | nightly | Разделяет массив с конца |
rsplit_array_mut<const M>(&mut self) -> (&mut [T], &mut [T; M]) | nightly | Разделяет изменяемый массив с конца |
impl<const N: usize> [u8; N]
| Метод | Версия | Описание |
|---|---|---|
as_ascii(&self) -> Option<&[AsciiChar; N]> | nightly | Преобразует байты в ASCII символы |
as_ascii_unchecked(&self) -> &[AsciiChar; N] | nightly | Небезопасное преобразование в ASCII |
impl<T, const N: usize> [MaybeUninit<T>; N]
| Метод | Версия | Описание |
|---|---|---|
transpose(self) -> MaybeUninit<[T; N]> | nightly | Транспонирование массива MaybeUninit |
impl<T, const N: usize> [Option<T>; N]
| Метод | Версия | Описание |
|---|---|---|
transpose(self) -> Option<[T; N]> | nightly | Транспонирование массива Option |
Реализации трейтов
From преобразования
| Источник | Назначение | Версия | Описание |
|---|---|---|---|
&[T; N] | Cow<'a, [T]> | 1.77.0 | Создание Cow без аллокации |
&[T; N] | Vec<T> | 1.74.0 | Копирование в Vec |
[(K, V); N] | BTreeMap<K, V> | 1.56.0 | Создание BTreeMap из массива пар |
[(K, V); N] | HashMap<K, V> | 1.56.0 | Создание HashMap из массива пар |
[T; N] | Arc<[T]> | 1.74.0 | Перемещение в Arc |
[T; N] | Box<[T]> | 1.45.0 | Перемещение в кучу |
[T; N] | Vec<T> | 1.44.0 | Перемещение в Vec |
[u16; 8] | IpAddr | 1.17.0 | IPv6 адрес из массива |
[u8; 16] | IpAddr | 1.17.0 | IPv6 адрес из байтов |
[u8; 4] | IpAddr | 1.17.0 | IPv4 адрес из байтов |
TryFrom преобразования
| Источник | Назначение | Версия | Описание |
|---|---|---|---|
&[T] | &[T; N] | 1.34.0 | Попытка создания ссылки на массив из среза |
&[T] | [T; N] | 1.34.0 | Копирование из среза в массив |
&mut [T] | &mut [T; N] | 1.34.0 | Создание изменяемой ссылки |
Box<[T]> | Box<[T; N]> | 1.43.0 | Попытка преобразования Box без аллокации |
Vec<T> | [T; N] | 1.48.0 | Получение массива из Vec |
Примеры
Базовое использование
#![allow(unused)] fn main() { let mut array: [i32; 3] = [0; 3]; array[1] = 1; array[2] = 2; assert_eq!([1, 2], &array[1..]); // Итерация по значению for x in array { print!("{x} "); } // Итерация по ссылке for x in &array { } }
Преобразования
#![allow(unused)] fn main() { let bytes: [u8; 3] = [1, 0, 2]; assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap())); assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap())); }
Использование map
#![allow(unused)] fn main() { let x = [1, 2, 3]; let y = x.map(|v| v + 1); assert_eq!(y, [2, 3, 4]); }
Изменения в изданиях Rust
Rust 2015/2018
array.into_iter() создаёт итератор по ссылкам (автоматическое приведение к срезу).
Rust 2021+
array.into_iter() работает через IntoIterator по значению. Для итерации по ссылкам используйте array.iter().
Рекомендация: Для совместимости между изданиями:
- Используйте
iter()для итерации по ссылкам - Используйте
IntoIterator::into_iter(array)для итерации по значению - Избегайте
array.into_iter()в изданиях 2015/2018
Примечания по производительности
Метод map на больших массивах может не оптимизироваться оптимально и потреблять много стекового пространства в режиме отладки. В критическом по производительности коду:
- Избегайте цепочек
mapна больших массивах - Рассмотрите использование
Iterator::mapчерез.iter()или.into_iter()
Примитивный тип char
Версия 1.0.0
Символьный тип.
Тип char представляет отдельный символ. Более конкретно, поскольку понятие "символ" не является четко определенным в Unicode, char представляет собой "скалярное значение Unicode" (Unicode scalar value).
Эта документация описывает ряд методов и реализаций трейтов для типа char. По техническим причинам существует дополнительная, отдельная документация в модуле std::char.
Валидность и размещение
char — это "скалярное значение Unicode", которое является любым "кодовой точкой Unicode", кроме суррогатных кодовых точек. Это имеет фиксированное числовое определение: кодовые точки находятся в диапазоне от 0 до 0x10FFFF включительно. Суррогатные кодовые точки, используемые UTF-16, находятся в диапазоне от 0xD800 до 0xDFFF.
Нельзя создать ни один char, будь то литерал или во время выполнения, который не является скалярным значением Unicode. Нарушение этого правила вызывает неопределенное поведение.
#![allow(unused)] fn main() { // Каждая из этих строк вызывает ошибку компиляции ['\u{D800}', '\u{DFFF}', '\u{110000}']; }
#![allow(unused)] fn main() { // Паника; from_u32 возвращает None char::from_u32(0xDE01).unwrap(); // Неопределенное поведение let _ = unsafe { char::from_u32_unchecked(0x110000) }; }
Скалярные значения Unicode также являются точным набором значений, которые могут быть закодированы в UTF-8. Поскольку значения char являются скалярными значениями Unicode и функции могут предполагать, что входящие значения str являются валидным UTF-8, безопасно хранить любой char в str или читать любой символ из str как char.
Пробел в валидных значениях char понятен компилятору, поэтому в примере ниже два диапазона считаются покрывающими весь диапазон возможных значений char, и нет ошибки для неисчерпывающего сопоставления.
#![allow(unused)] fn main() { let c: char = 'a'; match c { '\0' ..= '\u{D7FF}' => false, '\u{E000}' ..= '\u{10FFFF}' => true, }; }
Все скалярные значения Unicode являются валидными значениями char, но не все они представляют реальный символ. Многие скалярные значения Unicode в настоящее время не назначены символу, но могут быть назначены в будущем ("зарезервированы"); некоторые никогда не будут символами ("несимволы"); а некоторые могут иметь разное значение для разных пользователей ("частное использование").
char гарантированно имеет тот же размер, выравнивание и ABI вызова функций, что и u32 на всех платформах.
#![allow(unused)] fn main() { use std::alloc::Layout; assert_eq!(Layout::new::<char>(), Layout::new::<u32>()); }
Представление
char всегда имеет размер четыре байта. Это представление отличается от представления символа как части String. Например:
#![allow(unused)] fn main() { let v = vec!['h', 'e', 'l', 'l', 'o']; // пять элементов по четыре байта каждый assert_eq!(20, v.len() * size_of::<char>()); let s = String::from("hello"); // пять элементов по одному байту на элемент assert_eq!(5, s.len() * size_of::<u8>()); }
Как всегда, помните, что человеческая интуиция относительно "символа" может не соответствовать определениям Unicode. Например, несмотря на внешнее сходство, символ 'é' является одной кодовой точкой Unicode, а 'é' — двумя кодовыми точками Unicode:
#![allow(unused)] fn main() { let mut chars = "é".chars(); // U+00e9: 'latin small letter e with acute' assert_eq!(Some('\u{00e9}'), chars.next()); assert_eq!(None, chars.next()); let mut chars = "é".chars(); // U+0065: 'latin small letter e' assert_eq!(Some('\u{0065}'), chars.next()); // U+0301: 'combining acute accent' assert_eq!(Some('\u{0301}'), chars.next()); assert_eq!(None, chars.next()); }
Это означает, что содержимое первой строки выше поместится в char, а содержимое второй строки — нет. Попытка создать символьный литерал с содержимым второй строки вызывает ошибку:
#![allow(unused)] fn main() { error: character literal may only contain one codepoint: 'é' let c = 'é'; ^^^ }
Еще одно следствие фиксированного 4-байтового размера char заключается в том, что обработка каждого символа может использовать значительно больше памяти:
#![allow(unused)] fn main() { let s = String::from("love: ❤️"); let v: Vec<char> = s.chars().collect(); assert_eq!(12, size_of_val(&s[..])); assert_eq!(32, size_of_val(&v[..])); }
Реализации
Константы
| Константа | Значение | Версия | Описание |
|---|---|---|---|
MIN | '\0' | 1.83.0 | Наименьшая допустимая кодовая точка, которую может иметь char |
MAX | '\u{10ffff}' | 1.52.0 | Наибольшая допустимая кодовая точка, которую может иметь char |
MAX_LEN_UTF8 | 4 | 1.93.0 | Максимальное количество байтов, необходимое для кодирования char в UTF-8 |
MAX_LEN_UTF16 | 2 | 1.93.0 | Максимальное количество 2-байтовых единиц для кодирования char в UTF-16 |
REPLACEMENT_CHARACTER | '�' | 1.52.0 | Символ замены U+FFFD, используется для представления ошибок декодирования |
UNICODE_VERSION | (u8, u8, u8) | 1.52.0 | Версия Unicode, на которой основаны методы char и str |
Методы для создания и преобразования
| Метод | Версия | Описание | Безопасность |
|---|---|---|---|
decode_utf16<I>(iter: I) -> DecodeUtf16 | 1.52.0 | Создает итератор по UTF-16 кодам | Безопасный |
from_u32(i: u32) -> Option<char> | 1.52.0 (const: 1.67.0) | Конвертирует u32 в char | Безопасный |
from_u32_unchecked(i: u32) -> char | 1.52.0 (const: 1.81.0) | Конвертирует u32 в char без проверки | unsafe |
from_digit(num: u32, radix: u32) -> Option<char> | 1.52.0 (const: 1.67.0) | Конвертирует цифру в символ по основанию | Безопасный |
is_digit(self, radix: u32) -> bool | 1.0.0 (const: 1.87.0) | Проверяет, является ли символ цифрой в указанной системе счисления | Безопасный |
to_digit(self, radix: u32) -> Option<u32> | 1.0.0 (const: 1.67.0) | Конвертирует символ в цифру по основанию | Безопасный |
Методы экранирования
| Метод | Версия | Описание |
|---|---|---|
escape_unicode(self) -> EscapeUnicode | 1.0.0 | Возвращает итератор с шестнадцатеричным Unicode-экранированием |
escape_debug(self) -> EscapeDebug | 1.20.0 | Возвращает итератор с отладочным экранированием |
escape_default(self) -> EscapeDefault | 1.0.0 | Возвращает итератор с экранированием по умолчанию |
Методы кодирования и длины
| Метод | Версия | Описание |
|---|---|---|
len_utf8(self) -> usize | 1.0.0 (const: 1.52.0) | Возвращает количество байтов для кодирования в UTF-8 |
len_utf16(self) -> usize | 1.0.0 (const: 1.52.0) | Возвращает количество 16-битных единиц для кодирования в UTF-16 |
encode_utf8(self, dst: &mut [u8]) -> &mut str | 1.15.0 (const: 1.83.0) | Кодирует символ в UTF-8 в буфер |
encode_utf16(self, dst: &mut [u16]) -> &mut [u16] | 1.15.0 (const: 1.84.0) | Кодирует символ в UTF-16 в буфер |
Методы категорий Unicode
| Метод | Версия | Описание |
|---|---|---|
is_alphabetic(self) -> bool | 1.0.0 | Проверяет, является ли символ буквой (Alphabetic) |
is_lowercase(self) -> bool | 1.0.0 (const: 1.84.0) | Проверяет, является ли символ строчной буквой |
is_uppercase(self) -> bool | 1.0.0 (const: 1.84.0) | Проверяет, является ли символ прописной буквой |
is_whitespace(self) -> bool | 1.0.0 (const: 1.87.0) | Проверяет, является ли символ пробельным |
is_alphanumeric(self) -> bool | 1.0.0 | Проверяет, является ли символ буквенно-цифровым |
is_control(self) -> bool | 1.0.0 | Проверяет, является ли символ управляющим |
is_numeric(self) -> bool | 1.0.0 | Проверяет, является ли символ числовым |
Методы преобразования регистра
| Метод | Версия | Описание |
|---|---|---|
to_lowercase(self) -> ToLowercase | 1.0.0 | Возвращает итератор строчного отображения |
to_uppercase(self) -> ToUppercase | 1.0.0 | Возвращает итератор прописного отображения |
Методы проверки ASCII
| Метод | Версия | Описание |
|---|---|---|
is_ascii(&self) -> bool | 1.23.0 (const: 1.32.0) | Проверяет, находится ли значение в диапазоне ASCII |
as_ascii(&self) -> Option<AsciiChar> | nightly | Возвращает AsciiChar, если значение в диапазоне ASCII |
as_ascii_unchecked(&self) -> AsciiChar | nightly | Конвертирует в ASCII без проверки (unsafe) |
to_ascii_uppercase(&self) -> char | 1.23.0 (const: 1.52.0) | Конвертирует в ASCII прописную букву |
to_ascii_lowercase(&self) -> char | 1.23.0 (const: 1.52.0) | Конвертирует в ASCII строчную букву |
eq_ignore_ascii_case(&self, other: &char) -> bool | 1.23.0 (const: 1.52.0) | Проверяет равенство без учета регистра ASCII |
make_ascii_uppercase(&mut self) | 1.23.0 (const: 1.84.0) | Преобразует в ASCII прописную на месте |
make_ascii_lowercase(&mut self) | 1.23.0 (const: 1.84.0) | Преобразует в ASCII строчную на месте |
Детальные методы проверки ASCII
| Метод | Версия | Описание |
|---|---|---|
is_ascii_alphabetic(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII букву (A-Z, a-z) |
is_ascii_uppercase(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII прописную букву (A-Z) |
is_ascii_lowercase(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII строчную букву (a-z) |
is_ascii_alphanumeric(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII буквенно-цифровой символ |
is_ascii_digit(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII десятичную цифру (0-9) |
is_ascii_octdigit(&self) -> bool | nightly | Проверяет ASCII восьмеричную цифру (0-7) |
is_ascii_hexdigit(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII шестнадцатеричную цифру |
is_ascii_punctuation(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII пунктуацию |
is_ascii_graphic(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII графический символ |
is_ascii_whitespace(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII пробельный символ |
is_ascii_control(&self) -> bool | 1.24.0 (const: 1.47.0) | Проверяет ASCII управляющий символ |
Реализации трейтов
Основные трейты
| Трейт | Описание |
|---|---|
Clone | Клонирование символа |
Copy | Копирование символа |
Debug | Отладочное форматирование |
Display | Пользовательское форматирование |
Default | Значение по умолчанию ('\x00') |
Eq, PartialEq | Сравнение на равенство |
Ord, PartialOrd | Упорядочивание |
Hash | Хеширование |
FromStr | Парсинг из строки |
Конвертации
| Конвертация | Версия | Описание |
|---|---|---|
From<u8> for char | 1.13.0 | Преобразует байт (0x00..=0xFF) в символ |
From<char> for u32 | 1.13.0 | Преобразует символ в u32 |
From<char> for u64 | 1.51.0 | Преобразует символ в u64 |
From<char> for u128 | 1.51.0 | Преобразует символ в u128 |
From<char> for String | 1.46.0 | Создает String из символа |
TryFrom<char> for u8 | 1.59.0 | Пытается преобразовать символ в u8 |
TryFrom<char> for u16 | 1.74.0 | Пытается преобразовать символ в u16 |
TryFrom<u32> for char | 1.34.0 | Пытается преобразовать u32 в символ |
Сборщики
| Трейт | Версия | Описание |
|---|---|---|
FromIterator<char> for String | 1.0.0 | Создает String из итератора символов |
FromIterator<&char> for String | 1.17.0 | Создает String из итератора ссылок на символы |
Extend<char> for String | 1.0.0 | Расширяет String символами |
Extend<&char> for String | 1.2.0 | Расширяет String ссылками на символы |
Специальные трейты
| Трейт | Описание |
|---|---|
Pattern | Использование символа как шаблона для поиска в строках |
RangePattern | Использование символа в диапазонах шаблонов |
Step | Использование символа в итераторах по диапазонам |
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl Freeze for char impl RefUnwindSafe for char impl Send for char impl Sync for char impl Unpin for char impl UnwindSafe for char }
Примеры использования
#![allow(unused)] fn main() { // Создание символов let heart = '❤'; let sigma = 'Σ'; let emoji = '🚀'; // Проверка категорий assert!('A'.is_alphabetic()); assert!('5'.is_numeric()); assert!(' '.is_whitespace()); assert!('a'.is_lowercase()); assert!('Z'.is_uppercase()); // Преобразование регистра assert_eq!('A'.to_lowercase().to_string(), "a"); assert_eq!('ß'.to_uppercase().to_string(), "SS"); assert_eq!('i'.to_uppercase().to_string(), "I"); // не зависит от локали // Работа с ASCII assert!('a'.is_ascii()); assert!('❤'.is_ascii()); // false assert_eq!('A'.to_ascii_lowercase(), 'a'); assert_eq!('z'.to_ascii_uppercase(), 'Z'); // Кодирование let mut buf = [0; 4]; let s = 'ß'.encode_utf8(&mut buf); assert_eq!(s, "ß"); assert_eq!(s.len(), 2); // Цифры assert_eq!('7'.to_digit(10), Some(7)); assert_eq!('f'.to_digit(16), Some(15)); assert_eq!(char::from_digit(15, 16), Some('f')); // Экранирование assert_eq!('"'.escape_default().to_string(), "\\\""); assert_eq!('\n'.escape_debug().to_string(), "\\n"); assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}"); // Диапазоны символов for c in 'a'..='z' { assert!(c.is_ascii_lowercase()); } }
Важные замечания
- char ≠ байт:
charвсегда занимает 4 байта, тогда как символы в UTF-8 строке могут занимать от 1 до 4 байт - Суррогатные пары:
charне может содержать суррогатные кодовые точки (0xD800-0xDFFF) - Графические кластеры: Один видимый "символ" может состоять из нескольких
char(например, 'é' = 'e' + комбинирующий акцент) - Регистр не всегда обратим:
to_lowercase()иto_uppercase()не всегда являются обратными операциями - ASCII подмножество Unicode: Все ASCII символы являются валидными
char, но не наоборот
Производительность
charвсегда выровнен какu32, что обеспечивает быстрый доступ- Методы с пометкой
constмогут вычисляться во время компиляции - Кодирование/декодирование UTF-8/UTF-16 оптимизировано
- Проверки категорий Unicode используют предварительно вычисленные таблицы
Примитивный тип f64
64-битный тип с плавающей запятой (конкретно тип "binary64", определённый в IEEE 754-2008).
Этот тип очень похож на f32, но имеет повышенную точность за счёт использования вдвое большего количества битов.
Константы
| Константа | Значение | Описание |
|---|---|---|
RADIX | 2u32 | Основание системы счисления внутреннего представления. |
MANTISSA_DIGITS | 53u32 | Количество значащих цифр в системе счисления с основанием 2. |
DIGITS | 15u32 | Приблизительное количество значащих цифр в десятичной системе счисления. |
EPSILON | 2.2204460492503131E-16f64 | Машинное эпсилон для f64. |
MIN | -1.7976931348623157E+308f64 | Наименьшее конечное значение f64. |
MIN_POSITIVE | 2.2250738585072014E-308f64 | Наименьшее положительное нормализованное значение f64. |
MAX | 1.7976931348623157E+308f64 | Наибольшее конечное значение f64. |
MIN_EXP | -1021i32 | Минимальная возможная нормальная степень двойки. |
MAX_EXP | 1024i32 | Максимальная возможная степень двойки. |
MIN_10_EXP | -307i32 | Минимальный x, для которого 10^x является нормальным. |
MAX_10_EXP | 308i32 | Максимальный x, для которого 10^x является нормальным. |
NAN | NaN_f64 | Не число (NaN). |
INFINITY | +Inf_f64 | Бесконечность (∞). |
NEG_INFINITY | -Inf_f64 | Отрицательная бесконечность (−∞). |
Методы
Основные математические операции
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
floor(self) -> f64 | Возвращает наибольшее целое число, меньшее или равное self. | 1.90.0 | 1.0.0 | assert_eq!(3.7_f64.floor(), 3.0); |
ceil(self) -> f64 | Возвращает наименьшее целое число, большее или равное self. | 1.90.0 | 1.0.0 | assert_eq!(3.01_f64.ceil(), 4.0); |
round(self) -> f64 | Возвращает ближайшее целое число к self. | 1.90.0 | 1.0.0 | assert_eq!(3.3_f64.round(), 3.0); |
round_ties_even(self) -> f64 | Возвращает ближайшее целое число к числу. Половинные случаи округляются к числу с чётной младшей цифрой. | 1.90.0 | 1.77.0 | assert_eq!(3.5_f64.round_ties_even(), 4.0); |
trunc(self) -> f64 | Возвращает целую часть self. | 1.90.0 | 1.0.0 | assert_eq!(3.7_f64.trunc(), 3.0); |
fract(self) -> f64 | Возвращает дробную часть self. | 1.90.0 | 1.0.0 | let x = 3.6_f64; assert!(x.fract() - 0.6).abs() < 1e-10); |
mul_add(self, a: f64, b: f64) -> f64 | Точное умножение-сложение. Вычисляет (self * a) + b с одной ошибкой округления. | - | 1.0.0 | assert_eq!(10.0_f64.mul_add(4.0, 60.0), 100.0); |
div_euclid(self, rhs: f64) -> f64 | Вычисляет евклидово деление. | - | 1.38.0 | assert_eq!(7.0_f64.div_euclid(4.0), 1.0); |
rem_euclid(self, rhs: f64) -> f64 | Вычисляет наименьший неотрицательный остаток от деления self на rhs. | - | 1.38.0 | assert_eq!(7.0_f64.rem_euclid(4.0), 3.0); |
powi(self, n: i32) -> f64 | Возводит число в целую степень. | - | 1.0.0 | assert_eq!(2.0_f64.powi(2), 4.0); |
powf(self, n: f64) -> f64 | Возводит число в степень с плавающей запятой. | - | 1.0.0 | assert_eq!(2.0_f64.powf(2.0), 4.0); |
sqrt(self) -> f64 | Возвращает квадратный корень числа. | - | 1.0.0 | assert_eq!(4.0_f64.sqrt(), 2.0); |
exp(self) -> f64 | Возвращает e^(self) (экспоненциальная функция). | - | 1.0.0 | let e = 1.0_f64.exp(); |
exp2(self) -> f64 | Возвращает 2^(self). | - | 1.0.0 | assert_eq!(2.0_f64.exp2(), 4.0); |
ln(self) -> f64 | Возвращает натуральный логарифм числа. | - | 1.0.0 | let e = 1.0_f64.exp(); assert!(e.ln() - 1.0).abs() < 1e-10); |
log(self, base: f64) -> f64 | Возвращает логарифм числа по произвольному основанию. | - | 1.0.0 | assert_eq!(25.0_f64.log(5.0), 2.0); |
log2(self) -> f64 | Возвращает логарифм числа по основанию 2. | - | 1.0.0 | assert_eq!(4.0_f64.log2(), 2.0); |
log10(self) -> f64 | Возвращает логарифм числа по основанию 10. | - | 1.0.0 | assert_eq!(100.0_f64.log10(), 2.0); |
cbrt(self) -> f64 | Возвращает кубический корень числа. | - | 1.0.0 | assert_eq!(8.0_f64.cbrt(), 2.0); |
hypot(self, other: f64) -> f64 | Вычисляет расстояние между началом координат и точкой (x, y) на евклидовой плоскости. | - | 1.0.0 | assert_eq!(3.0_f64.hypot(4.0), 5.0); |
sin(self) -> f64 | Вычисляет синус числа (в радианах). | - | 1.0.0 | assert_eq!(std::f64::consts::FRAC_PI_2.sin(), 1.0); |
cos(self) -> f64 | Вычисляет косинус числа (в радианах). | - | 1.0.0 | assert_eq!((2.0 * std::f64::consts::PI).cos(), 1.0); |
tan(self) -> f64 | Вычисляет тангенс числа (в радианах). | - | 1.0.0 | assert_eq!(std::f64::consts::FRAC_PI_4.tan(), 1.0); |
asin(self) -> f64 | Вычисляет арксинус числа. Возвращаемое значение в радианах в диапазоне [-π/2, π/2]. | - | 1.0.0 | assert_eq!(1.0_f64.asin(), std::f64::consts::FRAC_PI_2); |
acos(self) -> f64 | Вычисляет арккосинус числа. Возвращаемое значение в радианах в диапазоне [0, π]. | - | 1.0.0 | assert_eq!(1.0_f64.acos(), 0.0); |
atan(self) -> f64 | Вычисляет арктангенс числа. Возвращаемое значение в радианах в диапазоне [-π/2, π/2]. | - | 1.0.0 | assert_eq!(1.0_f64.atan(), std::f64::consts::FRAC_PI_4); |
atan2(self, other: f64) -> f64 | Вычисляет арктангенс self (y) и other (x) в радианах с учётом квадранта. | - | 1.0.0 | assert_eq!(1.0_f64.atan2(1.0), std::f64::consts::FRAC_PI_4); |
sin_cos(self) -> (f64, f64) | Одновременно вычисляет синус и косинус числа. | - | 1.0.0 | let (sin, cos) = std::f64::consts::FRAC_PI_4.sin_cos(); |
exp_m1(self) -> f64 | Возвращает e^(self) - 1 точно даже для чисел, близких к нулю. | - | 1.0.0 | let x = 1e-16_f64; let approx = x + x * x / 2.0; |
ln_1p(self) -> f64 | Возвращает ln(1+n) (натуральный логарифм) точнее, чем при раздельном выполнении операций. | - | 1.0.0 | let x = 1e-16_f64; let approx = x - x * x / 2.0; |
sinh(self) -> f64 | Гиперболический синус. | - | 1.0.0 | let e = std::f64::consts::E; let x = 1.0_f64; |
cosh(self) -> f64 | Гиперболический косинус. | - | 1.0.0 | let e = std::f64::consts::E; let x = 1.0_f64; |
tanh(self) -> f64 | Гиперболический тангенс. | - | 1.0.0 | let e = std::f64::consts::E; let x = 1.0_f64; |
asinh(self) -> f64 | Обратный гиперболический синус. | - | 1.0.0 | assert_eq!(1.0_f64.sinh().asinh(), 1.0); |
acosh(self) -> f64 | Обратный гиперболический косинус. | - | 1.0.0 | assert_eq!(1.0_f64.cosh().acosh(), 1.0); |
atanh(self) -> f64 | Обратный гиперболический тангенс. | - | 1.0.0 | assert_eq!(std::f64::consts::FRAC_PI_6.tanh().atanh(), std::f64::consts::FRAC_PI_6); |
gamma(self) -> f64 | Гамма-функция. (экспериментальный) | - | Nightly | assert_eq!(5.0f64.gamma(), 24.0); |
ln_gamma(self) -> (f64, i32) | Натуральный логарифм абсолютного значения гамма-функции. (экспериментальный) | - | Nightly | assert_eq!(2.0f64.ln_gamma().0, 0.0); |
erf(self) -> f64 | Функция ошибок. (экспериментальный) | - | Nightly | let erf = (1.0 * std::f64::consts::FRAC_1_SQRT_2).erf(); |
erfc(self) -> f64 | Дополнительная функция ошибок. (экспериментальный) | - | Nightly | let x: f64 = 0.123; let one = x.erf() + x.erfc(); |
Проверка свойств чисел
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
is_nan(self) -> bool | Возвращает true, если значение равно NaN. | 1.83.0 | 1.0.0 | assert!(f64::NAN.is_nan()); |
is_infinite(self) -> bool | Возвращает true, если значение является положительной или отрицательной бесконечностью. | 1.83.0 | 1.0.0 | assert!(f64::INFINITY.is_infinite()); |
is_finite(self) -> bool | Возвращает true, если число не является ни бесконечностью, ни NaN. | 1.83.0 | 1.0.0 | assert!(7.0f64.is_finite()); |
is_subnormal(self) -> bool | Возвращает true, если число субнормальное. | 1.83.0 | 1.53.0 | assert!(1.0e-308_f64.is_subnormal()); |
is_normal(self) -> bool | Возвращает true, если число не является ни нулём, ни бесконечностью, ни субнормальным, ни NaN. | 1.83.0 | 1.0.0 | assert!(f64::MIN_POSITIVE.is_normal()); |
classify(self) -> FpCategory | Возвращает категорию числа с плавающей запятой. | 1.83.0 | 1.0.0 | assert_eq!(12.4_f64.classify(), FpCategory::Normal); |
is_sign_positive(self) -> bool | Возвращает true, если self имеет положительный знак. | 1.83.0 | 1.0.0 | assert!(7.0_f64.is_sign_positive()); |
is_sign_negative(self) -> bool | Возвращает true, если self имеет отрицательный знак. | 1.83.0 | 1.0.0 | assert!((-7.0_f64).is_sign_negative()); |
Соседние значения и преобразования
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
next_up(self) -> f64 | Возвращает наименьшее число, большее self. | 1.86.0 | 1.86.0 | assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); |
next_down(self) -> f64 | Возвращает наибольшее число, меньшее self. | 1.86.0 | 1.86.0 | assert_eq!(1.0f64.next_down(), 1.0 - f64::EPSILON); |
recip(self) -> f64 | Вычисляет обратное значение числа, 1/x. | 1.85.0 | 1.0.0 | assert_eq!(2.0_f64.recip(), 0.5); |
to_degrees(self) -> f64 | Преобразует радианы в градусы. | 1.85.0 | 1.0.0 | assert_eq!(std::f64::consts::PI.to_degrees(), 180.0); |
to_radians(self) -> f64 | Преобразует градусы в радианы. | 1.85.0 | 1.0.0 | assert_eq!(180.0_f64.to_radians(), std::f64::consts::PI); |
max(self, other: f64) -> f64 | Возвращает максимум двух чисел, игнорируя NaN. | 1.85.0 | 1.0.0 | assert_eq!(1.0_f64.max(2.0), 2.0); |
min(self, other: f64) -> f64 | Возвращает минимум двух чисел, игнорируя NaN. | 1.85.0 | 1.0.0 | assert_eq!(1.0_f64.min(2.0), 1.0); |
maximum(self, other: f64) -> f64 | Возвращает максимум двух чисел, распространяя NaN. (экспериментальный) | - | Nightly | assert_eq!(1.0_f64.maximum(2.0), 2.0); |
minimum(self, other: f64) -> f64 | Возвращает минимум двух чисел, распространяя NaN. (экспериментальный) | - | Nightly | assert_eq!(1.0_f64.minimum(2.0), 1.0); |
midpoint(self, other: f64) -> f64 | Вычисляет среднюю точку (среднее арифметическое) между self и rhs. | 1.85.0 | 1.85.0 | assert_eq!(1.0f64.midpoint(4.0), 2.5); |
to_int_unchecked<Int>(self) -> Int | Округляет к нулю и преобразует в любой примитивный целочисленный тип. | - | 1.44.0 | unsafe { assert_eq!(4.6_f64.to_int_unchecked::<u16>(), 4); } |
Работа с битовым представлением
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
to_bits(self) -> u64 | Прямое преобразование в u64. | 1.83.0 | 1.20.0 | assert_eq!((12.5f64).to_bits(), 0x4029000000000000); |
from_bits(v: u64) -> f64 | Прямое преобразование из u64. | 1.83.0 | 1.20.0 | assert_eq!(f64::from_bits(0x4029000000000000), 12.5); |
to_be_bytes(self) -> [u8; 8] | Возвращает представление числа в памяти в виде массива байтов в порядке big-endian. | 1.83.0 | 1.40.0 | let bytes = 12.5f64.to_be_bytes(); |
to_le_bytes(self) -> [u8; 8] | Возвращает представление числа в памяти в виде массива байтов в порядке little-endian. | 1.83.0 | 1.40.0 | let bytes = 12.5f64.to_le_bytes(); |
to_ne_bytes(self) -> [u8; 8] | Возвращает представление числа в памяти в виде массива байтов в порядке байтов целевой платформы. | 1.83.0 | 1.40.0 | let bytes = 12.5f64.to_ne_bytes(); |
from_be_bytes(bytes: [u8; 8]) -> f64 | Создаёт число из его представления в виде массива байтов в порядке big-endian. | 1.83.0 | 1.40.0 | let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); |
from_le_bytes(bytes: [u8; 8]) -> f64 | Создаёт число из его представления в виде массива байтов в порядке little-endian. | 1.83.0 | 1.40.0 | let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); |
from_ne_bytes(bytes: [u8; 8]) -> f64 | Создаёт число из его представления в памяти в виде массива байтов в порядке байтов целевой платформы. | 1.83.0 | 1.40.0 | let value = f64::from_ne_bytes(...); |
Сравнение и ограничение
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
total_cmp(&self, other: &f64) -> Ordering | Возвращает упорядочение между self и other в соответствии с предикатом totalOrder из IEEE 754. | - | 1.62.0 | assert!(1.0_f64.total_cmp(&2.0).is_lt()); |
clamp(self, min: f64, max: f64) -> f64 | Ограничивает значение определённым интервалом, если оно не равно NaN. | 1.85.0 | 1.50.0 | assert_eq!((-3.0f64).clamp(-2.0, 1.0), -2.0); |
abs(self) -> f64 | Вычисляет абсолютное значение self. | 1.85.0 | 1.0.0 | assert_eq!((-3.5_f64).abs(), 3.5); |
signum(self) -> f64 | Возвращает число, представляющее знак self. | 1.85.0 | 1.0.0 | assert_eq!(3.5_f64.signum(), 1.0); |
copysign(self, sign: f64) -> f64 | Возвращает число, состоящее из величины self и знака sign. | 1.85.0 | 1.35.0 | assert_eq!(3.5_f64.copysign(-0.42), -3.5_f64); |
Алгебраические операции (экспериментальные)
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
algebraic_add(self, rhs: f64) -> f64 | Сложение чисел с плавающей запятой, позволяющее оптимизации на основе алгебраических правил. (экспериментальный) | - | Nightly | - |
algebraic_sub(self, rhs: f64) -> f64 | Вычитание чисел с плавающей запятой, позволяющее оптимизации на основе алгебраических правил. (экспериментальный) | - | Nightly | - |
algebraic_mul(self, rhs: f64) -> f64 | Умножение чисел с плавающей запятой, позволяющее оптимизации на основе алгебраических правил. (экспериментальный) | - | Nightly | - |
algebraic_div(self, rhs: f64) -> f64 | Деление чисел с плавающей запятой, позволяющее оптимизации на основе алгебраических правил. (экспериментальный) | - | Nightly | - |
algebraic_rem(self, rhs: f64) -> f64 | Остаток от деления чисел с плавающей запятой, позволяющий оптимизации на основе алгебраических правил. (экспериментальный) | - | Nightly | - |
Устаревшие методы
| Метод | Описание | Версия | Статус | Примечание |
|---|---|---|---|---|
abs_sub(self, other: f64) -> f64 | Положительная разность двух чисел. | 1.0.0 | Устарело с 1.10.0 | Вероятно, вы имели в виду (self - other).abs() |
Примечания о точности
Многие функции помечены как имеющие неопределённую точность - это означает, что их точность может варьироваться в зависимости от платформы, версии Rust и даже между вызовами в одном исполнении.
Некоторые функции (например, sqrt, mul_add) гарантируют точность в соответствии со стандартом IEEE 754.
Примитивный тип fn
Указатели на функции, например fn(usize) -> bool.
Смотрите также трейты Fn, FnMut и FnOnce.
Указатели на функции — это указатели, которые указывают на код, а не на данные. Их можно вызывать так же, как функции. Как и ссылки, указатели на функции предполагаются ненулевыми, поэтому если вы хотите передать указатель на функцию через FFI и иметь возможность обрабатывать нулевые указатели, используйте тип Option<fn()> с требуемой сигнатурой.
Примечание: FFI требует дополнительной осторожности, чтобы гарантировать совпадение ABI для обеих сторон вызова. Точные требования в настоящее время не документированы.
Безопасность
Обычные указатели на функции получаются приведением либо обычных функций, либо замыканий, которые не захватывают окружение:
#![allow(unused)] fn main() { fn add_one(x: usize) -> usize { x + 1 } let ptr: fn(usize) -> usize = add_one; assert_eq!(ptr(5), 6); let clos: fn(usize) -> usize = |x| x + 5; assert_eq!(clos(5), 10); }
Помимо различий в зависимости от сигнатуры, указатели на функции бывают двух видов: безопасные и небезопасные. Обычные указатели fn() могут указывать только на безопасные функции, тогда как небезопасные указатели unsafe fn() могут указывать как на безопасные, так и на небезопасные функции.
#![allow(unused)] fn main() { fn add_one(x: usize) -> usize { x + 1 } unsafe fn add_one_unsafely(x: usize) -> usize { x + 1 } let safe_ptr: fn(usize) -> usize = add_one; // ОШИБКА: несовпадение типов: ожидалась обычная fn, найдена unsafe fn // let bad_ptr: fn(usize) -> usize = add_one_unsafely; let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely; let really_safe_ptr: unsafe fn(usize) -> usize = add_one; }
ABI
Кроме того, указатели на функции могут различаться в зависимости от используемого ABI. Это достигается добавлением ключевого слова extern перед типом, за которым следует соответствующий ABI. ABI по умолчанию — "Rust", т.е. fn() — это точно такой же тип, как extern "Rust" fn(). Указатель на функцию с ABI C будет иметь тип extern "C" fn().
Блоки extern "ABI" { ... } объявляют функции с ABI "ABI". Значение по умолчанию здесь — "C", т.е. функции, объявленные в блоке extern { ... }, имеют ABI "C".
Для получения дополнительной информации и списка поддерживаемых ABI см. раздел nomicon о соглашениях о вызовах.
Вариативные функции
Объявления внешних функций с ABI "C" или "cdecl" также могут быть вариативными, позволяя вызывать их с переменным числом аргументов. Обычные функции Rust, даже с extern "ABI", не могут быть вариативными. Для получения дополнительной информации см. раздел nomicon о вариативных функциях.
Создание указателей на функции
Когда bar — имя функции, выражение bar не является указателем на функцию. Скорее, оно обозначает значение неименуемого типа, который уникально идентифицирует функцию bar. Значение имеет нулевой размер, потому что тип уже идентифицирует функцию. Это имеет то преимущество, что "вызов" значения (оно реализует трейты Fn*) не требует динамической диспетчеризации.
Этот тип с нулевым размером приводится к обычному указателю на функцию. Например:
#![allow(unused)] fn main() { fn bar(x: i32) {} let not_bar_ptr = bar; // `not_bar_ptr` имеет нулевой размер, уникально идентифицируя `bar` assert_eq!(size_of_val(¬_bar_ptr), 0); let bar_ptr: fn(i32) = not_bar_ptr; // принудительное приведение к указателю на функцию assert_eq!(size_of_val(&bar_ptr), size_of::<usize>()); let footgun = &bar; // это общая ссылка на тип с нулевым размером, идентифицирующий `bar` }
Последняя строка показывает, что &bar также не является указателем на функцию. Скорее, это ссылка на специфичный для функции ZST (тип с нулевым размером). &bar практически никогда не является тем, что вам нужно, когда bar — функция.
Приведение к целым числам и обратно
Вы можете приводить указатели на функции непосредственно к целым числам:
#![allow(unused)] fn main() { let fnptr: fn(i32) -> i32 = |x| x+2; let fnptr_addr = fnptr as usize; }
Однако прямое приведение обратно невозможно. Необходимо использовать transmute:
#![allow(unused)] fn main() { let fnptr = fnptr_addr as *const (); let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) }; assert_eq!(fnptr(40), 42); }
Ключевой момент: мы сначала приводим к сырому указателю (as-приведение), а затем используем transmute для получения указателя на функцию. Это позволяет избежать transmute из целого числа в указатель, что может быть проблематично. Преобразование между сырыми указателями и указателями на функции (т.е. между двумя типами указателей) допустимо.
Примечание: Все это не переносимо на платформы, где указатели на функции и указатели на данные имеют разный размер.
Совместимость ABI
В общем случае, когда функция объявлена с одной сигнатурой, а вызывается через указатель на функцию с другой сигнатурой, эти две сигнатуры должны быть ABI-совместимыми, иначе вызов функции через этот указатель является неопределенным поведением. Совместимость ABI — гораздо более строгое требование, чем просто одинаковое размещение в памяти; например, даже если i32 и f32 имеют одинаковый размер и выравнивание, они могут передаваться в разных регистрах и, следовательно, не быть ABI-совместимыми.
Проблема совместимости ABI возникает только в коде, который изменяет тип указателей на функции, и в коде, который импортирует функции через блоки extern. Изменение типа указателей на функции чрезвычайно небезопасно (намного более небезопасно, чем даже transmute_copy), и должно происходить только в самых исключительных обстоятельствах. Большая часть кода на Rust просто импортирует функции через use. Так что, скорее всего, вам не нужно беспокоиться о совместимости ABI.
Но предположим такие обстоятельства, каковы правила? В этом разделе мы рассматриваем только ABI прямых вызовов Rust-to-Rust (когда и определение, и место вызова видны компилятору Rust), а не компоновку в целом — как только функции импортируются через блоки extern, появляются дополнительные факторы, которые мы здесь не рассматриваем. Обратите внимание, что это также относится к передаче/вызову функций через языковые границы с помощью указателей на функции.
Ничто в этом разделе не следует воспринимать как гарантию для вызовов не-Rust-to-Rust, даже с типами из core::ffi или libc.
Чтобы две сигнатуры считались ABI-совместимыми, они должны использовать совместимую строку ABI, принимать одинаковое количество аргументов, а типы отдельных аргументов и возвращаемый тип должны быть ABI-совместимыми. Строка ABI объявляется через extern "ABI" fn(...) -> ...; обратите внимание, что fn name(...) -> ... неявно использует строку ABI "Rust", а extern fn name(...) -> ... неявно использует строку ABI "C".
Строки ABI гарантированно совместимы, если они одинаковы, или если строка ABI вызывающей стороны имеет вид $X-unwind, а строка ABI вызываемой функции — $X, где $X — один из следующих: "C", "aapcs", "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64".
Следующие типы гарантированно ABI-совместимы:
| Группа типов | Условия совместимости |
|---|---|
*const T, *mut T, &T, &mut T, Box<T> (только Box<T, Global>), NonNull<T> | Все совместимы друг с другом для всех T. Также совместимы друг с другом для разных T, если они имеют одинаковый тип метаданных (<T as Pointee>::Metadata) |
usize | Совместим с беззнаковым целым типом uN того же размера |
isize | Совместим со знакомым целым типом iN того же размера |
char | Совместим с u32 |
Указатели на функции (fn) | Любые два типа fn совместимы друг с другом, если они имеют одинаковую строку ABI или строка ABI отличается только суффиксом -unwind, независимо от остальной части их сигнатуры |
| Типы с нулевым размером | Любые два типа с размером 0 и выравниванием 1 совместимы |
repr(transparent) тип T | Совместим со своим уникальным нетривиальным полем (единственным полем, которое не имеет размера 0 и выравнивания 1, если такое поле существует) |
i32 и NonZero<i32> | Совместимы (аналогично для всех других целочисленных типов) |
Тип T и перечисление E | Если T гарантированно подвергается оптимизации нулевого указателя, а E — перечисление, удовлетворяющее требованиям "option-like" |
Option-like перечисления (E) должны удовлетворять следующим требованиям:
- Используют представление Rust (без модификаторов
alignилиpacked) - Имеют ровно два варианта
- Один вариант имеет ровно одно поле типа
T - Все поля другого варианта имеют нулевой размер с выравниванием в 1 байт
Кроме того, совместимость ABI удовлетворяет следующим общим свойствам:
- Каждый тип ABI-совместим с самим собой
- Если
T1иT2ABI-совместимы, иT2иT3ABI-совместимы, тоT1иT3также ABI-совместимы (транзитивность) - Если
T1иT2ABI-совместимы, тоT2иT1также ABI-совместимы (симметричность)
Больше сигнатур могут быть ABI-совместимыми на конкретных целевых платформах, но на это нельзя полагаться, поскольку это не переносимо и не является стабильной гарантией.
Заметные случаи типов, которые в общем случае НЕ являются ABI-совместимыми:
boolиu8,i32иu32,charиi32: на некоторых платформах соглашения о вызовах для этих типов различаются в терминах гарантий для оставшихся битов в регистре, которые не используются значениемi32иf32также несовместимы, как уже упоминалось вышеstruct Foo(u32)иu32несовместимы (безrepr(transparent)), поскольку структуры являются агрегатными типами и часто передаются иначе, чем примитивы вродеi32
Важное замечание: Эти правила описывают, когда два полностью известных типа являются ABI-совместимыми. При рассмотрении совместимости ABI типа, объявленного в другом крейте (включая стандартную библиотеку), учтите, что любой тип, имеющий приватное поле или атрибут #[non_exhaustive], может изменить своё размещение как нефункциональное обновление, если не указано иное. Поэтому, например, даже если такой тип в настоящее время является 1-ZST или repr(transparent), это может измениться с любой версией библиотеки.
Если объявленная сигнатура и сигнатура указателя на функцию ABI-совместимы, то вызов функции ведёт себя так, как если бы каждый аргумент был преобразован (transmuted) из типа в указателе на функцию в тип в объявлении функции, а возвращаемое значение преобразовывалось из типа в объявлении в тип в указателе. Применяются все обычные предостережения и опасения относительно преобразования типов; например, если функция ожидает NonZero<i32>, а указатель на функцию использует ABI-совместимый тип Option<NonZero<i32>>, и значение, используемое для аргумента, — None, то этот вызов является неопределённым поведением, поскольку преобразование None::<NonZero<i32>> в NonZero<i32> нарушает требование ненулевого значения.
Реализации трейтов
В этой документации сокращение fn(T₁, T₂, …, Tₙ) используется для представления невариативных указателей на функции различной длины. Обратите внимание, что это удобное обозначение для избежания повторяющейся документации, а не допустимый синтаксис Rust.
Следующие трейты реализованы для указателей на функции с любым количеством аргументов и любым ABI:
| Трейт | Описание |
|---|---|
PartialEq | Частичное сравнение |
Eq | Полное сравнение (эквивалентность) |
PartialOrd | Частичное упорядочение |
Ord | Полное упорядочение |
Hash | Хеширование |
Pointer | Форматирование как указатель |
Debug | Отладочное форматирование |
Clone | Клонирование |
Copy | Копирование |
Send | Безопасная передача между потоками |
Sync | Безопасный доступ из нескольких потоков |
Unpin | Возможность перемещения из закреплённого состояния |
UnwindSafe | Безопасность при раскрутке стека |
RefUnwindSafe | Безопасность ссылок при раскрутке |
Примечание: Хотя этот тип реализует PartialEq, сравнение указателей на функции ненадёжно: указатели на одну и ту же функцию могут сравниваться как неравные (потому что функции дублируются в нескольких единицах компиляции), а указатели на разные функции могут сравниваться как равные (поскольку идентичные функции могут быть дедуплицированы внутри единицы компиляции).
Кроме того, все безопасные указатели на функции реализуют Fn, FnMut и FnOnce, потому что эти трейты специально известны компилятору.
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<Ret, T> Freeze for fn(T₁, T₂, …, Tₙ) -> Ret impl<Ret, T> RefUnwindSafe for fn(T₁, T₂, …, Tₙ) -> Ret impl<Ret, T> Send for fn(T₁, T₂, …, Tₙ) -> Ret impl<Ret, T> Sync for fn(T₁, T₂, …, Tₙ) -> Ret impl<Ret, T> Unpin for fn(T₁, T₂, …, Tₙ) -> Ret impl<Ret, T> UnwindSafe for fn(T₁, T₂, …, Tₙ) -> Ret }
Стандартные реализации (Blanket Implementations)
| Трейт | Для | Описание |
|---|---|---|
Any | T: 'static + ?Sized | Динамическая идентификация типа |
Borrow<T> | T: ?Sized | Заимствование |
BorrowMut<T> | T: ?Sized | Изменяемое заимствование |
CloneToUninit | T: Clone | Клонирование в неинициализированную память |
Debug | F: FnPtr | Отладочное форматирование для указателей на функции |
From<T> | Любой T | Преобразование из себя в себя |
Hash | F: FnPtr | Хеширование для указателей на функции |
Into<U> | U: From<T> | Преобразование в другой тип |
Ord | F: FnPtr | Упорядочение для указателей на функции |
PartialEq | F: FnPtr | Сравнение для указателей на функции |
PartialOrd | F: FnPtr | Частичное упорядочение для указателей на функции |
Pattern | F: FnMut(char) -> bool | Использование как шаблона для строк |
Pointer | F: FnPtr | Форматирование как указателя |
ToOwned | T: Clone | Получение владения |
TryFrom<U> | U: Into<T> | Попытка преобразования |
TryInto<U> | U: TryFrom<T> | Попытка преобразования |
Eq | F: FnPtr | Эквивалентность для указателей на функции |
Примеры использования
#![allow(unused)] fn main() { // Базовое использование указателей на функции fn multiply(x: i32, y: i32) -> i32 { x * y } let func_ptr: fn(i32, i32) -> i32 = multiply; assert_eq!(func_ptr(5, 3), 15); // Замыкания без захвата окружения также могут быть указателями на функции let add = |x, y| x + y; let add_ptr: fn(i32, i32) -> i32 = add; assert_eq!(add_ptr(2, 3), 5); // Использование с ABI extern "C" fn c_style() -> i32 { 42 } let c_ptr: extern "C" fn() -> i32 = c_style; // Указатели на функции как параметры fn apply_twice(f: fn(i32) -> i32, x: i32) -> i32 { f(f(x)) } fn square(x: i32) -> i32 { x * x } assert_eq!(apply_twice(square, 2), 16); // ((2²)²) = 16 // Указатели на функции в структурах struct Operation { op: fn(i32, i32) -> i32, name: &'static str, } let operations = [ Operation { op: |x, y| x + y, name: "add" }, Operation { op: |x, y| x - y, name: "subtract" }, Operation { op: |x, y| x * y, name: "multiply" }, ]; for op in &operations { println!("{}: {}", op.name, (op.op)(10, 5)); } }
Важные замечания
- Указатели на функции не являются замыканиями — они не могут захватывать окружение
- Отсутствие динамической диспетчеризации — вызов указателей на функции обычно происходит без накладных расходов
- ABI имеет значение — при межъязыковом взаимодействии необходимо указывать правильный ABI
- Ненадёжное сравнение — не следует полагаться на равенство указателей на функции
- Приведение типов — требует осторожности и обычно выполняется через
transmute
Примитивный тип i64
64-битное целое число со знаком.
Константы
| Константа | Значение | Описание | Версия | Пример |
|---|---|---|---|---|
MIN | -9_223_372_036_854_775_808i64 | Наименьшее значение, которое может быть представлено этим целочисленным типом (−2^63). | 1.43.0 | assert_eq!(i64::MIN, -9223372036854775808); |
MAX | 9_223_372_036_854_775_807i64 | Наибольшее значение, которое может быть представлено этим целочисленным типом (2^63 − 1). | 1.43.0 | assert_eq!(i64::MAX, 9223372036854775807); |
BITS | 64u32 | Размер этого целочисленного типа в битах. | 1.53.0 | assert_eq!(i64::BITS, 64); |
Методы
Битовая манипуляция и представление
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
count_ones(self) -> u32 | Возвращает количество единиц в двоичном представлении self. | 1.32.0 | 1.0.0 | let n = 0b100_0000i64; assert_eq!(n.count_ones(), 1); |
count_zeros(self) -> u32 | Возвращает количество нулей в двоичном представлении self. | 1.32.0 | 1.0.0 | assert_eq!(i64::MAX.count_zeros(), 1); |
leading_zeros(self) -> u32 | Возвращает количество ведущих нулей в двоичном представлении self. | 1.32.0 | 1.0.0 | let n = -1i64; assert_eq!(n.leading_zeros(), 0); |
trailing_zeros(self) -> u32 | Возвращает количество завершающих нулей в двоичном представлении self. | 1.32.0 | 1.0.0 | let n = -4i64; assert_eq!(n.trailing_zeros(), 2); |
leading_ones(self) -> u32 | Возвращает количество ведущих единиц в двоичном представлении self. | 1.46.0 | 1.46.0 | let n = -1i64; assert_eq!(n.leading_ones(), 64); |
trailing_ones(self) -> u32 | Возвращает количество завершающих единиц в двоичном представлении self. | 1.46.0 | 1.46.0 | let n = 3i64; assert_eq!(n.trailing_ones(), 2); |
isolate_highest_one(self) -> i64 | Возвращает self с установленным только самым старшим битом, или 0, если вход равен 0. (экспериментальный) | - | Nightly | let n: i64 = 0b_01100100; assert_eq!(n.isolate_highest_one(), 0b_01000000); |
isolate_lowest_one(self) -> i64 | Возвращает self с установленным только самым младшим битом, или 0, если вход равен 0. (экспериментальный) | - | Nightly | let n: i64 = 0b_01100100; assert_eq!(n.isolate_lowest_one(), 0b_00000100); |
highest_one(self) -> Option<u32> | Возвращает индекс самого старшего бита, установленного в единицу, или None, если self равен 0. (экспериментальный) | - | Nightly | assert_eq!(0b1_0000_i64.highest_one(), Some(4)); |
lowest_one(self) -> Option<u32> | Возвращает индекс самого младшего бита, установленного в единицу, или None, если self равен 0. (экспериментальный) | - | Nightly | assert_eq!(0b1_0000_i64.lowest_one(), Some(4)); |
cast_unsigned(self) -> u64 | Возвращает битовый шаблон self, переинтерпретированный как целое число без знака того же размера. | 1.87.0 | 1.87.0 | let n = -1i64; assert_eq!(n.cast_unsigned(), u64::MAX); |
rotate_left(self, n: u32) -> i64 | Сдвигает биты влево на указанное количество n, перенося усечённые биты в конец результирующего целого числа. | 1.32.0 | 1.0.0 | let n = 0xaa00000000006e1i64; let m = 0x6e10aa; assert_eq!(n.rotate_left(12), m); |
rotate_right(self, n: u32) -> i64 | Сдвигает биты вправо на указанное количество n, перенося усечённые биты в начало результирующего целого числа. | 1.32.0 | 1.0.0 | let n = 0x6e10aai64; let m = 0xaa00000000006e1; assert_eq!(n.rotate_right(12), m); |
swap_bytes(self) -> i64 | Обращает порядок байтов целого числа. | 1.32.0 | 1.0.0 | let n = 0x1234567890123456i64; assert_eq!(n.swap_bytes(), 0x5634129078563412); |
reverse_bits(self) -> i64 | Обращает порядок битов в целом числе. | 1.37.0 | 1.37.0 | let n = 0x1234567890123456i64; assert_eq!(n.reverse_bits(), 0x6a2c48091e6a2c48); |
from_be(x: i64) -> i64 | Преобразует целое число из формата big endian в порядок байтов целевой платформы. | 1.32.0 | 1.0.0 | let n = 0x1Ai64; if cfg!(target_endian = "big") { assert_eq!(i64::from_be(n), n) } else { assert_eq!(i64::from_be(n), n.swap_bytes()) } |
from_le(x: i64) -> i64 | Преобразует целое число из формата little endian в порядок байтов целевой платформы. | 1.32.0 | 1.0.0 | let n = 0x1Ai64; if cfg!(target_endian = "little") { assert_eq!(i64::from_le(n), n) } else { assert_eq!(i64::from_le(n), n.swap_bytes()) } |
to_be(self) -> i64 | Преобразует self в формат big endian из порядка байтов целевой платформы. | 1.32.0 | 1.0.0 | let n = 0x1Ai64; if cfg!(target_endian = "big") { assert_eq!(n.to_be(), n) } else { assert_eq!(n.to_be(), n.swap_bytes()) } |
to_le(self) -> i64 | Преобразует self в формат little endian из порядка байтов целевой платформы. | 1.32.0 | 1.0.0 | let n = 0x1Ai64; if cfg!(target_endian = "little") { assert_eq!(n.to_le(), n) } else { assert_eq!(n.to_le(), n.swap_bytes()) } |
Проверенные (Checked) арифметические операции
Возвращают Option<i64>, где None указывает на переполнение или деление на ноль.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
checked_add(self, rhs: i64) -> Option<i64> | Проверенное целочисленное сложение. Вычисляет self + rhs. | 1.47.0 | 1.0.0 | assert_eq!((i64::MAX - 2).checked_add(1), Some(i64::MAX - 1)); |
checked_add_unsigned(self, rhs: u64) -> Option<i64> | Проверенное сложение с целым числом без знака. Вычисляет self + rhs. | 1.66.0 | 1.66.0 | assert_eq!(1i64.checked_add_unsigned(2), Some(3)); |
checked_sub(self, rhs: i64) -> Option<i64> | Проверенное целочисленное вычитание. Вычисляет self - rhs. | 1.47.0 | 1.0.0 | assert_eq!((i64::MIN + 2).checked_sub(1), Some(i64::MIN + 1)); |
checked_sub_unsigned(self, rhs: u64) -> Option<i64> | Проверенное вычитание с целым числом без знака. Вычисляет self - rhs. | 1.66.0 | 1.66.0 | assert_eq!(1i64.checked_sub_unsigned(2), Some(-1)); |
checked_mul(self, rhs: i64) -> Option<i64> | Проверенное целочисленное умножение. Вычисляет self * rhs. | 1.47.0 | 1.0.0 | assert_eq!(i64::MAX.checked_mul(1), Some(i64::MAX)); |
checked_div(self, rhs: i64) -> Option<i64> | Проверенное целочисленное деление. Вычисляет self / rhs. | 1.52.0 | 1.0.0 | assert_eq!((i64::MIN + 1).checked_div(-1), Some(9223372036854775807)); |
checked_div_euclid(self, rhs: i64) -> Option<i64> | Проверенное евклидово деление. Вычисляет self.div_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!((i64::MIN + 1).checked_div_euclid(-1), Some(9223372036854775807)); |
checked_div_exact(self, rhs: i64) -> Option<i64> | Проверенное целочисленное деление без остатка. Вычисляет self / rhs. (экспериментальный) | - | Nightly | assert_eq!((i64::MIN + 1).checked_div_exact(-1), Some(9223372036854775807)); |
checked_rem(self, rhs: i64) -> Option<i64> | Проверенный целочисленный остаток. Вычисляет self % rhs. | 1.52.0 | 1.7.0 | assert_eq!(5i64.checked_rem(2), Some(1)); |
checked_rem_euclid(self, rhs: i64) -> Option<i64> | Проверенный евклидов остаток. Вычисляет self.rem_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!(5i64.checked_rem_euclid(2), Some(1)); |
checked_neg(self) -> Option<i64> | Проверенное отрицание. Вычисляет -self. | 1.47.0 | 1.7.0 | assert_eq!(5i64.checked_neg(), Some(-5)); |
checked_shl(self, rhs: u32) -> Option<i64> | Проверенный сдвиг влево. Вычисляет self << rhs. | 1.47.0 | 1.7.0 | assert_eq!(0x1i64.checked_shl(4), Some(0x10)); |
checked_shr(self, rhs: u32) -> Option<i64> | Проверенный сдвиг вправо. Вычисляет self >> rhs. | 1.47.0 | 1.7.0 | assert_eq!(0x10i64.checked_shr(4), Some(0x1)); |
checked_abs(self) -> Option<i64> | Проверенное абсолютное значение. Вычисляет self.abs(). | 1.47.0 | 1.13.0 | assert_eq!((-5i64).checked_abs(), Some(5)); |
checked_pow(self, exp: u32) -> Option<i64> | Проверенное возведение в степень. Вычисляет self.pow(exp). | 1.50.0 | 1.34.0 | assert_eq!(8i64.checked_pow(2), Some(64)); |
checked_isqrt(self) -> Option<i64> | Возвращает квадратный корень числа, округлённый вниз. Возвращает None, если self отрицательно. | 1.84.0 | 1.84.0 | assert_eq!(10i64.checked_isqrt(), Some(3)); |
checked_next_multiple_of(self, rhs: i64) -> Option<i64> | Если rhs положительно, вычисляет наименьшее значение, большее или равное self, кратное rhs. Если rhs отрицательно, вычисляет наибольшее значение, меньшее или равное self, кратное rhs. Возвращает None, если rhs равен нулю или операция приведёт к переполнению. (экспериментальный) | - | Nightly | assert_eq!(16_i64.checked_next_multiple_of(8), Some(16)); |
checked_ilog(self, base: i64) -> Option<u32> | Возвращает логарифм числа по произвольному основанию, округлённый вниз. Возвращает None, если число отрицательно или равно нулю, или если основание меньше 2. | 1.67.0 | 1.67.0 | assert_eq!(5i64.checked_ilog(5), Some(1)); |
checked_ilog2(self) -> Option<u32> | Возвращает логарифм числа по основанию 2, округлённый вниз. Возвращает None, если число отрицательно или равно нулю. | 1.67.0 | 1.67.0 | assert_eq!(2i64.checked_ilog2(), Some(1)); |
checked_ilog10(self) -> Option<u32> | Возвращает логарифм числа по основанию 10, округлённый вниз. Возвращает None, если число отрицательно или равно нулю. | 1.67.0 | 1.67.0 | assert_eq!(10i64.checked_ilog10(), Some(1)); |
Строгие (Strict) арифметические операции
Вызывают панику при переполнении или недопустимых операциях.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
strict_add(self, rhs: i64) -> i64 | Строгое целочисленное сложение. Вычисляет self + rhs. | 1.91.0 | 1.91.0 | assert_eq!((i64::MAX - 2).strict_add(1), i64::MAX - 1); |
strict_add_unsigned(self, rhs: u64) -> i64 | Строгое сложение с целым числом без знака. Вычисляет self + rhs. | 1.91.0 | 1.91.0 | assert_eq!(1i64.strict_add_unsigned(2), 3); |
strict_sub(self, rhs: i64) -> i64 | Строгое целочисленное вычитание. Вычисляет self - rhs. | 1.91.0 | 1.91.0 | assert_eq!((i64::MIN + 2).strict_sub(1), i64::MIN + 1); |
strict_sub_unsigned(self, rhs: u64) -> i64 | Строгое вычитание с целым числом без знака. Вычисляет self - rhs. | 1.91.0 | 1.91.0 | assert_eq!(1i64.strict_sub_unsigned(2), -1); |
strict_mul(self, rhs: i64) -> i64 | Строгое целочисленное умножение. Вычисляет self * rhs. | 1.91.0 | 1.91.0 | assert_eq!(i64::MAX.strict_mul(1), i64::MAX); |
strict_div(self, rhs: i64) -> i64 | Строгое целочисленное деление. Вычисляет self / rhs. | 1.91.0 | 1.91.0 | assert_eq!((i64::MIN + 1).strict_div(-1), 9223372036854775807); |
strict_div_euclid(self, rhs: i64) -> i64 | Строгое евклидово деление. Вычисляет self.div_euclid(rhs). | 1.91.0 | 1.91.0 | assert_eq!((i64::MIN + 1).strict_div_euclid(-1), 9223372036854775807); |
strict_rem(self, rhs: i64) -> i64 | Строгий целочисленный остаток. Вычисляет self % rhs. | 1.91.0 | 1.91.0 | assert_eq!(5i64.strict_rem(2), 1); |
strict_rem_euclid(self, rhs: i64) -> i64 | Строгий евклидов остаток. Вычисляет self.rem_euclid(rhs). | 1.91.0 | 1.91.0 | assert_eq!(5i64.strict_rem_euclid(2), 1); |
strict_neg(self) -> i64 | Строгое отрицание. Вычисляет -self. | 1.91.0 | 1.91.0 | assert_eq!(5i64.strict_neg(), -5); |
strict_shl(self, rhs: u32) -> i64 | Строгий сдвиг влево. Вычисляет self << rhs. | 1.91.0 | 1.91.0 | assert_eq!(0x1i64.strict_shl(4), 0x10); |
strict_shr(self, rhs: u32) -> i64 | Строгий сдвиг вправо. Вычисляет self >> rhs. | 1.91.0 | 1.91.0 | assert_eq!(0x10i64.strict_shr(4), 0x1); |
strict_abs(self) -> i64 | Строгое абсолютное значение. Вычисляет self.abs(). | 1.91.0 | 1.91.0 | assert_eq!((-5i64).strict_abs(), 5); |
strict_pow(self, exp: u32) -> i64 | Строгое возведение в степень. Вычисляет self.pow(exp). | 1.91.0 | 1.91.0 | assert_eq!(8i64.strict_pow(2), 64); |
Непроверенные (Unchecked) арифметические операции
Небезопасные операции, предполагающие отсутствие переполнения.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
unchecked_add(self, rhs: i64) -> i64 | Непроверенное целочисленное сложение. Вычисляет self + rhs. | 1.79.0 | 1.79.0 | unsafe { assert_eq!(5i64.unchecked_add(2), 7); } |
unchecked_sub(self, rhs: i64) -> i64 | Непроверенное целочисленное вычитание. Вычисляет self - rhs. | 1.79.0 | 1.79.0 | unsafe { assert_eq!(5i64.unchecked_sub(2), 3); } |
unchecked_mul(self, rhs: i64) -> i64 | Непроверенное целочисленное умножение. Вычисляет self * rhs. | 1.79.0 | 1.79.0 | unsafe { assert_eq!(5i64.unchecked_mul(2), 10); } |
unchecked_div_exact(self, rhs: i64) -> i64 | Непроверенное целочисленное деление без остатка. Вычисляет self / rhs. (экспериментальный) | - | Nightly | unsafe { assert_eq!(64i64.unchecked_div_exact(2), 32); } |
unchecked_neg(self) -> i64 | Непроверенное отрицание. Вычисляет -self. (экспериментальный) | - | Nightly | unsafe { assert_eq!(5i64.unchecked_neg(), -5); } |
unchecked_shl(self, rhs: u32) -> i64 | Непроверенный сдвиг влево. Вычисляет self << rhs. (экспериментальный) | - | Nightly | unsafe { assert_eq!(0x1i64.unchecked_shl(4), 0x10); } |
unchecked_shl_exact(self, rhs: u32) -> i64 | Непроверенный точный сдвиг влево. Вычисляет self << rhs. (экспериментальный) | - | Nightly | unsafe { assert_eq!(0x1i64.unchecked_shl_exact(4), 0x10); } |
unchecked_shr(self, rhs: u32) -> i64 | Непроверенный сдвиг вправо. Вычисляет self >> rhs. (экспериментальный) | - | Nightly | unsafe { assert_eq!(0x10i64.unchecked_shr(4), 0x1); } |
unchecked_shr_exact(self, rhs: u32) -> i64 | Непроверенный точный сдвиг вправо. Вычисляет self >> rhs. (экспериментальный) | - | Nightly | unsafe { assert_eq!(0x10i64.unchecked_shr_exact(4), 0x1); } |
Насыщающая (Saturating) арифметика
Операции, которые насыщаются на границах типа вместо переполнения.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
saturating_add(self, rhs: i64) -> i64 | Насыщающее целочисленное сложение. Вычисляет self + rhs. | 1.47.0 | 1.0.0 | assert_eq!(100i64.saturating_add(1), 101); |
saturating_add_unsigned(self, rhs: u64) -> i64 | Насыщающее сложение с целым числом без знака. Вычисляет self + rhs. | 1.66.0 | 1.66.0 | assert_eq!(1i64.saturating_add_unsigned(2), 3); |
saturating_sub(self, rhs: i64) -> i64 | Насыщающее целочисленное вычитание. Вычисляет self - rhs. | 1.47.0 | 1.0.0 | assert_eq!(100i64.saturating_sub(127), -27); |
saturating_sub_unsigned(self, rhs: u64) -> i64 | Насыщающее вычитание с целым числом без знака. Вычисляет self - rhs. | 1.66.0 | 1.66.0 | assert_eq!(100i64.saturating_sub_unsigned(127), -27); |
saturating_neg(self) -> i64 | Насыщающее целочисленное отрицание. Вычисляет -self. | 1.47.0 | 1.45.0 | assert_eq!(100i64.saturating_neg(), -100); |
saturating_abs(self) -> i64 | Насыщающее абсолютное значение. Вычисляет self.abs(). | 1.47.0 | 1.45.0 | assert_eq!(100i64.saturating_abs(), 100); |
saturating_mul(self, rhs: i64) -> i64 | Насыщающее целочисленное умножение. Вычисляет self * rhs. | 1.47.0 | 1.7.0 | assert_eq!(10i64.saturating_mul(12), 120); |
saturating_div(self, rhs: i64) -> i64 | Насыщающее целочисленное деление. Вычисляет self / rhs. | 1.58.0 | 1.58.0 | assert_eq!(5i64.saturating_div(2), 2); |
saturating_pow(self, exp: u32) -> i64 | Насыщающее целочисленное возведение в степень. Вычисляет self.pow(exp). | 1.50.0 | 1.34.0 | assert_eq!((-4i64).saturating_pow(3), -64); |
Циклическая (Wrapping) арифметика
Операции, которые циклически оборачиваются на границах типа.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
wrapping_add(self, rhs: i64) -> i64 | Циклическое (модулярное) сложение. Вычисляет self + rhs. | 1.32.0 | 1.0.0 | assert_eq!(100i64.wrapping_add(27), 127); |
wrapping_add_unsigned(self, rhs: u64) -> i64 | Циклическое сложение с целым числом без знака. Вычисляет self + rhs. | 1.66.0 | 1.66.0 | assert_eq!(100i64.wrapping_add_unsigned(27), 127); |
wrapping_sub(self, rhs: i64) -> i64 | Циклическое (модулярное) вычитание. Вычисляет self - rhs. | 1.32.0 | 1.0.0 | assert_eq!(0i64.wrapping_sub(127), -127); |
wrapping_sub_unsigned(self, rhs: u64) -> i64 | Циклическое вычитание с целым числом без знака. Вычисляет self - rhs. | 1.66.0 | 1.66.0 | assert_eq!(0i64.wrapping_sub_unsigned(127), -127); |
wrapping_mul(self, rhs: i64) -> i64 | Циклическое (модулярное) умножение. Вычисляет self * rhs. | 1.32.0 | 1.0.0 | assert_eq!(10i64.wrapping_mul(12), 120); |
wrapping_div(self, rhs: i64) -> i64 | Циклическое (модулярное) деление. Вычисляет self / rhs. | 1.52.0 | 1.2.0 | assert_eq!(100i64.wrapping_div(10), 10); |
wrapping_div_euclid(self, rhs: i64) -> i64 | Циклическое евклидово деление. Вычисляет self.div_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!(100i64.wrapping_div_euclid(10), 10); |
wrapping_rem(self, rhs: i64) -> i64 | Циклический (модулярный) остаток. Вычисляет self % rhs. | 1.52.0 | 1.2.0 | assert_eq!(100i64.wrapping_rem(10), 0); |
wrapping_rem_euclid(self, rhs: i64) -> i64 | Циклический евклидов остаток. Вычисляет self.rem_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!(100i64.wrapping_rem_euclid(10), 0); |
wrapping_neg(self) -> i64 | Циклическое (модулярное) отрицание. Вычисляет -self. | 1.32.0 | 1.2.0 | assert_eq!(100i64.wrapping_neg(), -100); |
wrapping_shl(self, rhs: u32) -> i64 | Безопасный битовый сдвиг влево; даёт self << mask(rhs). | 1.32.0 | 1.2.0 | assert_eq!((-1i64).wrapping_shl(7), -128); |
wrapping_shr(self, rhs: u32) -> i64 | Безопасный битовый сдвиг вправо; даёт self >> mask(rhs). | 1.32.0 | 1.2.0 | assert_eq!((-128i64).wrapping_shr(7), -1); |
wrapping_abs(self) -> i64 | Циклическое (модулярное) абсолютное значение. Вычисляет self.abs(). | 1.32.0 | 1.13.0 | assert_eq!(100i64.wrapping_abs(), 100); |
wrapping_pow(self, exp: u32) -> i64 | Циклическое (модулярное) возведение в степень. Вычисляет self.pow(exp). | 1.50.0 | 1.34.0 | assert_eq!(3i64.wrapping_pow(4), 81); |
unsigned_abs(self) -> u64 | Вычисляет абсолютное значение self без циклического оборачивания или паники. | 1.51.0 | 1.51.0 | assert_eq!(100i64.unsigned_abs(), 100u64); |
Операции с переполнением (Overflowing)
Возвращают кортеж (i64, bool), где bool указывает на наличие переполнения.
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
overflowing_add(self, rhs: i64) -> (i64, bool) | Вычисляет self + rhs. | 1.32.0 | 1.7.0 | assert_eq!(5i64.overflowing_add(2), (7, false)); |
carrying_add(self, rhs: i64, carry: bool) -> (i64, bool) | Вычисляет self + rhs + carry и проверяет переполнение. (экспериментальный) | - | Nightly | let (sum1, overflow) = a1.carrying_add(b1, carry1); |
overflowing_add_unsigned(self, rhs: u64) -> (i64, bool) | Вычисляет self + rhs с беззнаковым rhs. | 1.66.0 | 1.66.0 | assert_eq!(1i64.overflowing_add_unsigned(2), (3, false)); |
overflowing_sub(self, rhs: i64) -> (i64, bool) | Вычисляет self - rhs. | 1.32.0 | 1.7.0 | assert_eq!(5i64.overflowing_sub(2), (3, false)); |
borrowing_sub(self, rhs: i64, borrow: bool) -> (i64, bool) | Вычисляет self − rhs − borrow и проверяет переполнение. (экспериментальный) | - | Nightly | let (diff1, overflow) = a1.borrowing_sub(b1, borrow1); |
overflowing_sub_unsigned(self, rhs: u64) -> (i64, bool) | Вычисляет self - rhs с беззнаковым rhs. | 1.66.0 | 1.66.0 | assert_eq!(1i64.overflowing_sub_unsigned(2), (-1, false)); |
overflowing_mul(self, rhs: i64) -> (i64, bool) | Вычисляет умножение self и rhs. | 1.32.0 | 1.7.0 | assert_eq!(5i64.overflowing_mul(2), (10, false)); |
widening_mul(self, rhs: i64) -> (u64, i64) | Вычисляет полное произведение self * rhs без возможности переполнения. (экспериментальный) | - | Nightly | assert_eq!(5i32.widening_mul(-2), (4294967286, -1)); |
carrying_mul(self, rhs: i64, carry: i64) -> (u64, i64) | Вычисляет "полное умножение" self * rhs + carry без возможности переполнения. (экспериментальный) | - | Nightly | assert_eq!(5i32.carrying_mul(-2, 0), (4294967286, -1)); |
carrying_mul_add(self, rhs: i64, carry: i64, add: i64) -> (u64, i64) | Вычисляет "полное умножение" self * rhs + carry + add без возможности переполнения. (экспериментальный) | - | Nightly | assert_eq!(5i32.carrying_mul_add(-2, 0, 0), (4294967286, -1)); |
overflowing_div(self, rhs: i64) -> (i64, bool) | Вычисляет делитель, когда self делится на rhs. | 1.52.0 | 1.7.0 | assert_eq!(5i64.overflowing_div(2), (2, false)); |
overflowing_div_euclid(self, rhs: i64) -> (i64, bool) | Вычисляет частное евклидова деления self.div_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!(5i64.overflowing_div_euclid(2), (2, false)); |
overflowing_rem(self, rhs: i64) -> (i64, bool) | Вычисляет остаток от деления self на rhs. | 1.52.0 | 1.7.0 | assert_eq!(5i64.overflowing_rem(2), (1, false)); |
overflowing_rem_euclid(self, rhs: i64) -> (i64, bool) | Переполняющий евклидов остаток. Вычисляет self.rem_euclid(rhs). | 1.52.0 | 1.38.0 | assert_eq!(5i64.overflowing_rem_euclid(2), (1, false)); |
overflowing_neg(self) -> (i64, bool) | Отрицает self, с переполнением, если это равно минимальному значению. | 1.32.0 | 1.7.0 | assert_eq!(2i64.overflowing_neg(), (-2, false)); |
overflowing_shl(self, rhs: u32) -> (i64, bool) | Сдвигает self влево на rhs бит. | 1.32.0 | 1.7.0 | assert_eq!(0x1i64.overflowing_shl(4), (0x10, false)); |
overflowing_shr(self, rhs: u32) -> (i64, bool) | Сдвигает self вправо на rhs бит. | 1.32.0 | 1.7.0 | assert_eq!(0x10i64.overflowing_shr(4), (0x1, false)); |
overflowing_abs(self) -> (i64, bool) | Вычисляет абсолютное значение self. | 1.32.0 | 1.13.0 | assert_eq!(10i64.overflowing_abs(), (10, false)); |
overflowing_pow(self, exp: u32) -> (i64, bool) | Возводит self в степень exp, используя возведение в квадрат. | 1.50.0 | 1.34.0 | assert_eq!(3i64.overflowing_pow(4), (81, false)); |
Прочие арифметические операции
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
pow(self, exp: u32) -> i64 | Возводит self в степень exp, используя возведение в квадрат. | 1.50.0 | 1.0.0 | assert_eq!(2i64.pow(5), 32); |
isqrt(self) -> i64 | Возвращает квадратный корень числа, округлённый вниз. | 1.84.0 | 1.84.0 | assert_eq!(10i64.isqrt(), 3); |
div_euclid(self, rhs: i64) -> i64 | Вычисляет частное евклидова деления self на rhs. | 1.52.0 | 1.38.0 | let a: i64 = 7; assert_eq!(a.div_euclid(4), 1); |
rem_euclid(self, rhs: i64) -> i64 | Вычисляет наименьший неотрицательный остаток от деления self на rhs. | 1.52.0 | 1.38.0 | let a: i64 = 7; assert_eq!(a.rem_euclid(4), 3); |
div_floor(self, rhs: i64) -> i64 | Вычисляет частное от деления self на rhs, округляя результат в сторону отрицательной бесконечности. (экспериментальный) | - | Nightly | assert_eq!(8i64.div_floor(3), 2); |
div_ceil(self, rhs: i64) -> i64 | Вычисляет частное от деления self на rhs, округляя результат в сторону положительной бесконечности. (экспериментальный) | - | Nightly | assert_eq!(8i64.div_ceil(3), 3); |
next_multiple_of(self, rhs: i64) -> i64 | Если rhs положительно, вычисляет наименьшее значение, большее или равное self, кратное rhs. Если rhs отрицательно, вычисляет наибольшее значение, меньшее или равное self, кратное rhs. (экспериментальный) | - | Nightly | assert_eq!(23_i64.next_multiple_of(8), 24); |
ilog(self, base: i64) -> u32 | Возвращает логарифм числа по произвольному основанию, округлённый вниз. | 1.67.0 | 1.67.0 | assert_eq!(5i64.ilog(5), 1); |
ilog2(self) -> u32 | Возвращает логарифм числа по основанию 2, округлённый вниз. | 1.67.0 | 1.67.0 | assert_eq!(2i64.ilog2(), 1); |
ilog10(self) -> u32 | Возвращает логарифм числа по основанию 10, округлённый вниз. | 1.67.0 | 1.67.0 | assert_eq!(10i64.ilog10(), 1); |
abs(self) -> i64 | Вычисляет абсолютное значение self. | 1.32.0 | 1.0.0 | assert_eq!(10i64.abs(), 10); |
abs_diff(self, other: i64) -> u64 | Вычисляет абсолютную разницу между self и other. | 1.60.0 | 1.60.0 | assert_eq!(100i64.abs_diff(80), 20u64); |
signum(self) -> i64 | Возвращает число, представляющее знак self. | 1.47.0 | 1.0.0 | assert_eq!(10i64.signum(), 1); |
is_positive(self) -> bool | Возвращает true, если self положительно, и false, если число равно нулю или отрицательно. | 1.32.0 | 1.0.0 | assert!(10i64.is_positive()); |
is_negative(self) -> bool | Возвращает true, если self отрицательно, и false, если число равно нулю или положительно. | 1.32.0 | 1.0.0 | assert!((-10i64).is_negative()); |
div_exact(self, rhs: i64) -> Option<i64> | Целочисленное деление без остатка. Вычисляет self / rhs. Возвращает None, если self % rhs != 0. (экспериментальный) | - | Nightly | assert_eq!(64i64.div_exact(2), Some(32)); |
shl_exact(self, rhs: u32) -> Option<i64> | Точный сдвиг влево. Вычисляет self << rhs, если это можно обратить без потерь. (экспериментальный) | - | Nightly | assert_eq!(0x1i64.shl_exact(4), Some(0x10)); |
shr_exact(self, rhs: u32) -> Option<i64> | Точный сдвиг вправо. Вычисляет self >> rhs, если это можно обратить без потерь. (экспериментальный) | - | Nightly | assert_eq!(0x10i64.shr_exact(4), Some(0x1)); |
unbounded_shl(self, rhs: u32) -> i64 | Неограниченный сдвиг влево. Вычисляет self << rhs, без ограничения значения rhs. | 1.87.0 | 1.87.0 | assert_eq!(0x1i64.unbounded_shl(4), 0x10); |
unbounded_shr(self, rhs: u32) -> i64 | Неограниченный сдвиг вправо. Вычисляет self >> rhs, без ограничения значения rhs. | 1.87.0 | 1.87.0 | assert_eq!(0x10i64.unbounded_shr(4), 0x1); |
midpoint(self, rhs: i64) -> i64 | Вычисляет среднюю точку (среднее арифметическое) между self и rhs. | 1.87.0 | 1.87.0 | assert_eq!(0i64.midpoint(4), 2); |
Преобразования в/из байтов
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
to_be_bytes(self) -> [u8; 8] | Возвращает представление этого целого числа в памяти в виде массива байтов в порядке big-endian (сетевом). | 1.44.0 | 1.32.0 | let bytes = 0x1234567890123456i64.to_be_bytes(); assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]); |
to_le_bytes(self) -> [u8; 8] | Возвращает представление этого целого числа в памяти в виде массива байтов в порядке little-endian. | 1.44.0 | 1.32.0 | let bytes = 0x1234567890123456i64.to_le_bytes(); assert_eq!(bytes, [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]); |
to_ne_bytes(self) -> [u8; 8] | Возвращает представление этого целого числа в памяти в виде массива байтов в порядке байтов целевой платформы. | 1.44.0 | 1.32.0 | let bytes = 0x1234567890123456i64.to_ne_bytes(); assert_eq!(bytes, if cfg!(target_endian = "big") { [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56] } else { [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12] }); |
from_be_bytes(bytes: [u8; 8]) -> i64 | Создаёт целочисленное значение из его представления в виде массива байтов в порядке big-endian. | 1.44.0 | 1.32.0 | let value = i64::from_be_bytes([0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]); assert_eq!(value, 0x1234567890123456); |
from_le_bytes(bytes: [u8; 8]) -> i64 | Создаёт целочисленное значение из его представления в виде массива байтов в порядке little-endian. | 1.44.0 | 1.32.0 | let value = i64::from_le_bytes([0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]); assert_eq!(value, 0x1234567890123456); |
from_ne_bytes(bytes: [u8; 8]) -> i64 | Создаёт целочисленное значение из его представления в памяти в виде массива байтов в порядке байтов целевой платформы. | 1.44.0 | 1.32.0 | let value = i64::from_ne_bytes(if cfg!(target_endian = "big") { [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56] } else { [0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12] }); assert_eq!(value, 0x1234567890123456); |
Разбор из строк и ASCII
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
from_str_radix(src: &str, radix: u32) -> Result<i64, ParseIntError> | Разбирает целое число из строкового среза с цифрами в заданной системе счисления. | 1.82.0 | 1.0.0 | assert_eq!(i64::from_str_radix("A", 16), Ok(10)); |
from_ascii(src: &[u8]) -> Result<i64, ParseIntError> | Разбирает целое число из среза ASCII-байтов с десятичными цифрами. (экспериментальный) | - | Nightly | assert_eq!(i64::from_ascii(b"+10"), Ok(10)); |
from_ascii_radix(src: &[u8], radix: u32) -> Result<i64, ParseIntError> | Разбирает целое число из среза ASCII-байтов с цифрами в заданной системе счисления. (экспериментальный) | - | Nightly | assert_eq!(i64::from_ascii_radix(b"A", 16), Ok(10)); |
Форматирование
| Метод | Описание | Константность | Версия | Пример |
|---|---|---|---|---|
format_into(self, buf: &mut NumBuffer<i64>) -> &str | Позволяет записать целое число (в знаковом десятичном формате) в переменную buf типа NumBuffer, передаваемую по изменяемой ссылке. (экспериментальный) | - | Nightly | use core::fmt::NumBuffer; let n = 0i64; let mut buf = NumBuffer::new(); assert_eq!(n.format_into(&mut buf), "0"); |
Устаревшие методы
| Метод | Описание | Константность | Версия | Примечание |
|---|---|---|---|---|
min_value() -> i64 | Возвращает наименьшее значение, которое может быть представлено этим целочисленным типом. | 1.32.0 | 1.0.0 | Устарело. Вместо этого следует использовать i64::MIN. |
max_value() -> i64 | Возвращает наибольшее значение, которое может быть представлено этим целочисленным типом. | 1.32.0 | 1.0.0 | Устарело. Вместо этого следует использовать i64::MAX. |
Примитивный тип isize
Размерный знаковый целочисленный тип.
Размер этого примитива соответствует количеству байт, необходимых для ссылки на любое место в памяти. Например, на 32-битной цели это 4 байта, а на 64-битной — 8 байтов.
Примечание: В данной документации представлены реализации для 64-битной архитектуры. На 32-битной архитектуре значения констант и поведение методов будут отличаться.
Константы
| Константа | Значение | Версия | Описание |
|---|---|---|---|
MIN | -9_223_372_036_854_775_808 | 1.43.0 | Наименьшее значение (−2⁶³) |
MAX | 9_223_372_036_854_775_807 | 1.43.0 | Наибольшее значение (2⁶³ − 1) |
BITS | 64 | 1.53.0 | Размер типа в битах |
Таблицы методов
Битовая арифметика
| Метод | Версия | Описание |
|---|---|---|
count_ones() | 1.0.0 | Количество единиц в двоичном представлении |
count_zeros() | 1.0.0 | Количество нулей в двоичном представлении |
leading_zeros() | 1.0.0 | Количество ведущих нулей |
trailing_zeros() | 1.0.0 | Количество хвостовых нулей |
leading_ones() | 1.46.0 | Количество ведущих единиц |
trailing_ones() | 1.46.0 | Количество хвостовых единиц |
rotate_left(n) | 1.0.0 | Циклический сдвиг влево |
rotate_right(n) | 1.0.0 | Циклический сдвиг вправо |
swap_bytes() | 1.0.0 | Обратный порядок байтов |
reverse_bits() | 1.37.0 | Обратный порядок битов |
from_be(x) | 1.0.0 | Преобразование из big-endian |
from_le(x) | 1.0.0 | Преобразование из little-endian |
to_be() | 1.0.0 | Преобразование в big-endian |
to_le() | 1.0.0 | Преобразование в little-endian |
cast_unsigned() | 1.87.0 | Преобразование битового шаблона в usize |
Экспериментальные битовые методы
| Метод | Флаг | Описание |
|---|---|---|
isolate_highest_one() | isolate_most_least_significant_one | Оставляет только старший бит |
isolate_lowest_one() | isolate_most_least_significant_one | Оставляет только младший бит |
highest_one() | int_lowest_highest_one | Индекс старшего установленного бита |
lowest_one() | int_lowest_highest_one | Индекс младшего установленного бита |
shl_exact(rhs) | exact_bitshifts | Точный сдвиг влево с проверкой |
shr_exact(rhs) | exact_bitshifts | Точный сдвиг вправо с проверкой |
div_exact(rhs) | exact_div | Деление без остатка |
checked_div_exact(rhs) | exact_div | Проверенное деление без остатка |
Арифметика с проверкой переполнения
| Метод | Операция | Версия | Поведение при переполнении |
|---|---|---|---|
checked_add(rhs) | + | 1.0.0 | Возвращает None |
checked_sub(rhs) | - | 1.0.0 | Возвращает None |
checked_mul(rhs) | * | 1.0.0 | Возвращает None |
checked_div(rhs) | / | 1.0.0 | Возвращает None при делении на 0 или переполнении |
checked_rem(rhs) | % | 1.7.0 | Возвращает None при делении на 0 или переполнении |
checked_neg() | -x | 1.7.0 | Возвращает None для MIN |
checked_shl(rhs) | << | 1.7.0 | Возвращает None при слишком большом сдвиге |
checked_shr(rhs) | >> | 1.7.0 | Возвращает None при слишком большом сдвиге |
checked_abs() | abs() | 1.13.0 | Возвращает None для MIN |
checked_pow(exp) | pow() | 1.34.0 | Возвращает None при переполнении |
checked_isqrt() | isqrt() | 1.84.0 | Возвращает None для отрицательных чисел |
Строгие методы (всегда паникуют при переполнении)
| Метод | Версия | Паникует при |
|---|---|---|
strict_add(rhs) | 1.91.0 | Переполнении |
strict_sub(rhs) | 1.91.0 | Переполнении |
strict_mul(rhs) | 1.91.0 | Переполнении |
strict_div(rhs) | 1.91.0 | Делении на 0 или MIN / -1 |
strict_rem(rhs) | 1.91.0 | Делении на 0 или MIN % -1 |
strict_neg() | 1.91.0 | -MIN |
strict_shl(rhs) | 1.91.0 | Сдвиге ≥ BITS |
strict_shr(rhs) | 1.91.0 | Сдвиге ≥ BITS |
strict_abs() | 1.91.0 | abs(MIN) |
strict_pow(exp) | 1.91.0 | Переполнении |
Небезопасные методы (без проверок)
| Метод | Флаг | Небезопасность при |
|---|---|---|
unchecked_add(rhs) | - | Переполнении |
unchecked_sub(rhs) | - | Переполнении |
unchecked_mul(rhs) | - | Переполнении |
unchecked_neg() | unchecked_neg | -MIN |
unchecked_shl(rhs) | unchecked_shifts | Сдвиге ≥ BITS |
unchecked_shr(rhs) | unchecked_shifts | Сдвиге ≥ BITS |
unchecked_shl_exact(rhs) | exact_bitshifts | Невозможности обратить сдвиг |
unchecked_shr_exact(rhs) | exact_bitshifts | Невозможности обратить сдвиг |
unchecked_div_exact(rhs) | exact_div | Делении на 0, остатке или MIN / -1 |
Насыщающая арифметика
| Метод | Операция | Версия | Поведение при переполнении |
|---|---|---|---|
saturating_add(rhs) | + | 1.0.0 | Возвращает MAX или MIN |
saturating_sub(rhs) | - | 1.0.0 | Возвращает MAX или MIN |
saturating_mul(rhs) | * | 1.7.0 | Возвращает MAX или MIN |
saturating_div(rhs) | / | 1.58.0 | Возвращает MAX или MIN |
saturating_neg() | -x | 1.45.0 | Возвращает MAX для MIN |
saturating_abs() | abs() | 1.45.0 | Возвращает MAX для MIN |
saturating_pow(exp) | pow() | 1.34.0 | Возвращает MAX или MIN |
Обёртывающая арифметика
| Метод | Операция | Версия | Поведение при переполнении |
|---|---|---|---|
wrapping_add(rhs) | + | 1.0.0 | Обёртывание по модулю |
wrapping_sub(rhs) | - | 1.0.0 | Обёртывание по модулю |
wrapping_mul(rhs) | * | 1.0.0 | Обёртывание по модулю |
wrapping_div(rhs) | / | 1.2.0 | Возвращает MIN для MIN / -1 |
wrapping_rem(rhs) | % | 1.2.0 | Возвращает 0 для MIN % -1 |
wrapping_neg() | -x | 1.2.0 | Возвращает MIN для MIN |
wrapping_shl(rhs) | << | 1.2.0 | Маскирование сдвига |
wrapping_shr(rhs) | >> | 1.2.0 | Маскирование сдвига |
wrapping_abs() | abs() | 1.13.0 | Возвращает MIN для MIN |
wrapping_pow(exp) | pow() | 1.34.0 | Обёртывание по модулю |
Арифметика с переполнением (возвращает флаг)
| Метод | Операция | Версия | Возвращает |
|---|---|---|---|
overflowing_add(rhs) | + | 1.7.0 | (результат, флаг_переполнения) |
overflowing_sub(rhs) | - | 1.7.0 | (результат, флаг_переполнения) |
overflowing_mul(rhs) | * | 1.7.0 | (результат, флаг_переполнения) |
overflowing_div(rhs) | / | 1.7.0 | (результат, флаг_переполнения) |
overflowing_rem(rhs) | % | 1.7.0 | (результат, флаг_переполнения) |
overflowing_neg() | -x | 1.7.0 | (результат, флаг_переполнения) |
overflowing_shl(rhs) | << | 1.7.0 | (результат, флаг_сдвига) |
overflowing_shr(rhs) | >> | 1.7.0 | (результат, флаг_сдвига) |
overflowing_abs() | abs() | 1.13.0 | (результат, флаг_переполнения) |
overflowing_pow(exp) | pow() | 1.34.0 | (результат, флаг_переполнения) |
Работа с беззнаковыми числами
| Метод | Операция | Версия | Тип аргумента |
|---|---|---|---|
checked_add_unsigned(rhs) | + | 1.66.0 | usize |
checked_sub_unsigned(rhs) | - | 1.66.0 | usize |
strict_add_unsigned(rhs) | + | 1.91.0 | usize |
strict_sub_unsigned(rhs) | - | 1.91.0 | usize |
saturating_add_unsigned(rhs) | + | 1.66.0 | usize |
saturating_sub_unsigned(rhs) | - | 1.66.0 | usize |
wrapping_add_unsigned(rhs) | + | 1.66.0 | usize |
wrapping_sub_unsigned(rhs) | - | 1.66.0 | usize |
overflowing_add_unsigned(rhs) | + | 1.66.0 | usize |
overflowing_sub_unsigned(rhs) | - | 1.66.0 | usize |
Евклидова арифметика
| Метод | Версия | Описание |
|---|---|---|
div_euclid(rhs) | 1.38.0 | Евклидово деление |
rem_euclid(rhs) | 1.38.0 | Евклидов остаток |
checked_div_euclid(rhs) | 1.38.0 | Проверенное евклидово деление |
checked_rem_euclid(rhs) | 1.38.0 | Проверенный евклидов остаток |
strict_div_euclid(rhs) | 1.91.0 | Строгое евклидово деление |
strict_rem_euclid(rhs) | 1.91.0 | Строгий евклидов остаток |
wrapping_div_euclid(rhs) | 1.38.0 | Обёртывающее евклидово деление |
wrapping_rem_euclid(rhs) | 1.38.0 | Обёртывающий евклидов остаток |
overflowing_div_euclid(rhs) | 1.38.0 | Евклидово деление с переполнением |
overflowing_rem_euclid(rhs) | 1.38.0 | Евклидов остаток с переполнением |
Устаревшие методы
| Метод | Замена | Версия | Статус |
|---|---|---|---|
min_value() | MIN | 1.0.0 | Устарел |
max_value() | MAX | 1.0.0 | Устарел |
Математические функции
| Метод | Описание | Версия |
|---|---|---|
abs() | Абсолютное значение | 1.0.0 |
signum() | Знак числа | 1.0.0 |
is_positive() | Проверка положительности | 1.0.0 |
is_negative() | Проверка отрицательности | 1.0.0 |
pow(exp) | Возведение в степень | 1.0.0 |
isqrt() | Целочисленный квадратный корень | 1.84.0 |
ilog(base) | Логарифм по произвольному основанию | 1.67.0 |
ilog2() | Двоичный логарифм | 1.67.0 |
ilog10() | Десятичный логарифм | 1.67.0 |
checked_ilog(base) | Проверенный логарифм | 1.67.0 |
checked_ilog2() | Проверенный двоичный логарифм | 1.67.0 |
checked_ilog10() | Проверенный десятичный логарифм | 1.67.0 |
unsigned_abs() | Беззнаковое абсолютное значение | 1.51.0 |
abs_diff(other) | Абсолютная разница | 1.60.0 |
midpoint(rhs) | Средняя точка | 1.87.0 |
Округление деления
| Метод | Флаг | Описание |
|---|---|---|
div_floor(rhs) | int_roundings | Деление с округлением вниз |
div_ceil(rhs) | int_roundings | Деление с округлением вверх |
next_multiple_of(rhs) | int_roundings | Следующее кратное |
checked_next_multiple_of(rhs) | int_roundings | Проверенное следующее кратное |
Расширенная арифметика (для больших чисел)
| Метод | Флаг | Описание |
|---|---|---|
carrying_add(rhs, carry) | bigint_helper_methods | Сложение с переносом |
borrowing_sub(rhs, borrow) | bigint_helper_methods | Вычитание с заёмом |
widening_mul(rhs) | bigint_helper_methods | Расширенное умножение |
carrying_mul(rhs, carry) | bigint_helper_methods | Умножение с переносом |
carrying_mul_add(rhs, carry, add) | bigint_helper_methods | Умножение с переносом и сложением |
Работа с байтами
| Метод | Порядок байтов | Версия | Возвращает |
|---|---|---|---|
to_be_bytes() | Big-endian | 1.32.0 | [u8; 8] |
to_le_bytes() | Little-endian | 1.32.0 | [u8; 8] |
to_ne_bytes() | Native | 1.32.0 | [u8; 8] |
from_be_bytes(bytes) | Big-endian | 1.32.0 | isize |
from_le_bytes(bytes) | Little-endian | 1.32.0 | isize |
from_ne_bytes(bytes) | Native | 1.32.0 | isize |
Парсинг строк
| Метод | Источник | Версия |
|---|---|---|
from_str_radix(src, radix) | &str | 1.0.0 |
from_ascii(src) | &[u8] | nightly |
from_ascii_radix(src, radix) | &[u8] | nightly |
from_str(src) (impl FromStr) | &str | 1.0.0 |
Форматирование
| Метод | Флаг | Описание |
|---|---|---|
format_into(buf) | int_format_into | Форматирование в буфер |
Специальные методы сдвига
| Метод | Версия | Описание |
|---|---|---|
unbounded_shl(rhs) | 1.87.0 | Сдвиг влево без ограничений |
unbounded_shr(rhs) | 1.87.0 | Сдвиг вправо без ограничений |
Реализации трейтов
Арифметические операторы
| Трейт | Операция | Реализация |
|---|---|---|
Add, AddAssign | +, += | Сложение |
Sub, SubAssign | -, -= | Вычитание |
Mul, MulAssign | *, *= | Умножение |
Div, DivAssign | /, /= | Деление |
Rem, RemAssign | %, %= | Остаток |
Neg | -x | Отрицание |
BitAnd, BitAndAssign | &, &= | Побитовое И |
BitOr, BitOrAssign | ` | , |
BitXor, BitXorAssign | ^, ^= | Побитовое XOR |
Not | ! | Побитовое НЕ |
Shl, ShlAssign | <<, <<= | Сдвиг влево |
Shr, ShrAssign | >>, >>= | Сдвиг вправо |
Трейты форматирования
| Трейт | Формат | Пример |
|---|---|---|
Display | Десятичный | 42 |
Debug | Отладочный | 42 |
Binary | Двоичный | 0b101010 |
Octal | Восьмеричный | 0o52 |
LowerHex | Нижний регистр hex | 0x2a |
UpperHex | Верхний регистр hex | 0x2A |
LowerExp | Научная нотация (нижний) | 4.2e1 |
UpperExp | Научная нотация (верхний) | 4.2E1 |
Трейты преобразования
| Преобразование | Метод | Особенности |
|---|---|---|
From<bool> | from(bool) | 0 для false, 1 для true |
From<i8> | from(i8) | Без потерь |
From<i16> | from(i16) | Без потерь |
From<u8> | from(u8) | Без потерь |
TryFrom<i32> | try_from(i32) | С проверкой диапазона |
TryFrom<i64> | try_from(i64) | С проверкой диапазона |
TryFrom<i128> | try_from(i128) | С проверкой диапазона |
TryFrom<u16> | try_from(u16) | С проверкой диапазона |
TryFrom<u32> | try_from(u32) | С проверкой диапазона |
TryFrom<u64> | try_from(u64) | С проверкой диапазона |
TryFrom<u128> | try_from(u128) | С проверкой диапазона |
TryFrom<usize> | try_from(usize) | С проверкой диапазона |
Прочие важные трейты
| Трейт | Назначение |
|---|---|
Default | Значение по умолчанию (0) |
Clone, Copy | Клонирование и копирование |
Hash | Хеширование |
PartialOrd, Ord | Сравнение |
PartialEq, Eq | Равенство |
Step, TrustedStep | Итерация по диапазонам |
Product, Sum | Агрегация итераторов |
FromStr | Парсинг из строки |
Примеры
Базовое использование
#![allow(unused)] fn main() { let x: isize = 42; let y: isize = -10; assert_eq!(x + y, 32); assert_eq!(x.abs_diff(y), 52); }
Проверка переполнения
#![allow(unused)] fn main() { assert_eq!(isize::MAX.checked_add(1), None); assert_eq!(isize::MAX.saturating_add(1), isize::MAX); assert_eq!(isize::MAX.wrapping_add(1), isize::MIN); }
Работа с битами
#![allow(unused)] fn main() { let n: isize = 0b1010; assert_eq!(n.count_ones(), 2); assert_eq!(n.rotate_left(2), 0b101000); }
Преобразование байтов
#![allow(unused)] fn main() { let bytes = 0x1234567890123456isize.to_be_bytes(); assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]); let value = isize::from_be_bytes(bytes); assert_eq!(value, 0x1234567890123456); }
Евклидова арифметика
#![allow(unused)] fn main() { let a: isize = -7; let b: isize = 4; assert_eq!(a.div_euclid(b), -2); assert_eq!(a.rem_euclid(b), 1); }
Логарифмы
#![allow(unused)] fn main() { assert_eq!(16isize.ilog2(), 4); assert_eq!(100isize.ilog10(), 2); assert_eq!(125isize.ilog(5), 3); }
Особенности
- Размерность: Размер
isizeзависит от целевой архитектуры (обычно 32 или 64 бита). - Переполнение: При переполнении в отладочной сборке происходит паника, в релизной — обёртывание.
- Деление на ноль: Всегда вызывает панику.
MIN.abs(): Вызывает панику в отладочной сборке, возвращаетMINв релизной.- Эндрианность: Методы
to_be_bytes(),to_le_bytes(),to_ne_bytes()учитывают порядок байтов.
Примитивный тип pointer
Сырые указатели (raw pointers) *const T и *mut T
Смотрите также модуль std::ptr.
Работа с сырыми указателями в Rust встречается редко и обычно ограничена несколькими паттернами. Сырые указатели могут быть:
- Выходящими за границы (
out-of-bounds) - Невыровненными (
unaligned) - Нулевыми (
null)
Однако при загрузке из или записи в сырой указатель он должен быть валидным для данного доступа и выровненным. При использовании выражений доступа к полю, индексации кортежа, массива или среза на сыром указателе применяются правила арифметики указателей в пределах границ.
Запись через сырой указатель с помощью *ptr = data вызывает drop на старом значении, поэтому если тип имеет деструктор (drop glue) и память ещё не инициализирована, необходимо использовать write - иначе drop будет вызван на неинициализированной памяти.
Используйте функции null и null_mut для создания нулевых указателей, а метод is_null типов *const T и *mut T для проверки на null. Типы *const T и *mut T также определяют метод offset для арифметики указателей.
Распространённые способы создания сырых указателей
1. Приведение ссылки (&T) или изменяемой ссылки (&mut T)
#![allow(unused)] fn main() { let my_num: i32 = 10; let my_num_ptr: *const i32 = &my_num; let mut my_speed: i32 = 88; let my_speed_ptr: *mut i32 = &mut my_speed; }
Чтобы получить указатель на упакованное значение (Box), разыменуйте box:
#![allow(unused)] fn main() { let my_num: Box<i32> = Box::new(10); let my_num_ptr: *const i32 = &*my_num; let mut my_speed: Box<i32> = Box::new(88); let my_speed_ptr: *mut i32 = &mut *my_speed; }
Это не забирает владение исходным выделением памяти и не требует управления ресурсами позже, но нельзя использовать указатель после окончания его времени жизни.
2. Потребление box'а (Box<T>)
Функция into_raw потребляет box и возвращает сырой указатель. Она не уничтожает T и не освобождает память.
#![allow(unused)] fn main() { let my_speed: Box<i32> = Box::new(88); let my_speed: *mut i32 = Box::into_raw(my_speed); // Забрав владение исходным `Box<T>`, мы обязаны позже собрать его для уничтожения unsafe { drop(Box::from_raw(my_speed)); } }
Примечание: вызов drop здесь для ясности - он указывает, что мы закончили работу с данным значением и его следует уничтожить.
3. Создание с помощью &raw
Вместо приведения ссылки к сырому указателю можно использовать операторы сырого заимствования &raw const (для *const T) и &raw mut (для *mut T). Эти операторы позволяют создавать сырые указатели на поля, на которые нельзя создать ссылку (без возникновения неопределённого поведения), например, на невыровненное поле. Это может быть необходимо при работе с упакованными структурами (packed structs) или неинициализированной памятью.
#![allow(unused)] fn main() { #[derive(Debug, Default, Copy, Clone)] #[repr(C, packed)] struct S { aligned: u8, unaligned: u32, } let s = S::default(); let p = &raw const s.unaligned; // невозможно с приведением }
4. Получение из C
#![allow(unused)] fn main() { #[allow(unused_extern_crates)] extern crate libc; unsafe { let my_num: *mut i32 = libc::malloc(size_of::<i32>()) as *mut i32; if my_num.is_null() { panic!("failed to allocate memory"); } libc::free(my_num as *mut core::ffi::c_void); } }
Обычно вы не будете буквально использовать malloc и free из Rust, но C API часто возвращают указатели, поэтому они являются распространённым источником сырых указателей в Rust.
Реализации методов
Методы для *const T
| Метод | Версия | Описание |
|---|---|---|
is_null(self) -> bool | 1.0.0 (const: 1.84.0) | Возвращает true, если указатель нулевой |
cast<U>(self) -> *const U | 1.38.0 (const: 1.38.0) | Приводит к указателю другого типа |
try_cast_aligned<U>(self) -> Option<*const U> | nightly | Пытается привести к указателю другого типа с проверкой выравнивания |
with_metadata_of<U>(self, meta: *const U) -> *const U | nightly | Использует адресное значение в новом указателе другого типа |
cast_mut(self) -> *mut T | 1.65.0 (const: 1.65.0) | Изменяет константность без изменения типа |
addr(self) -> usize | 1.84.0 | Получает "адресную" часть указателя |
expose_provenance(self) -> usize | 1.84.0 | Раскрывает "происхождение" указателя для будущего использования |
with_addr(self, addr: usize) -> *const T | 1.84.0 | Создаёт новый указатель с заданным адресом и происхождением self |
map_addr(self, f: FnOnce(usize) -> usize) -> *const T | 1.84.0 | Создаёт новый указатель, отображая адрес self на новый |
to_raw_parts(self) -> (*const (), Metadata) | nightly | Разбирает (возможно, широкий) указатель на компоненты |
as_ref<'a>(self) -> Option<&'a T> | 1.9.0 (const: 1.84.0) | Возвращает None, если указатель нулевой, иначе ссылку на значение |
as_ref_unchecked<'a>(self) -> &'a T | nightly | Возвращает ссылку на значение за указателем без проверки на null |
as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>> | nightly | Аналогично as_ref, но допускает неинициализированные значения |
offset(self, count: isize) -> *const T | 1.0.0 (const: 1.61.0) | Добавляет знаковое смещение к указателю |
byte_offset(self, count: isize) -> *const T | 1.75.0 (const: 1.75.0) | Добавляет знаковое смещение в байтах |
wrapping_offset(self, count: isize) -> *const T | 1.16.0 (const: 1.61.0) | Добавляет знаковое смещение с оборачивающей арифметикой |
wrapping_byte_offset(self, count: isize) -> *const T | 1.75.0 (const: 1.75.0) | Добавляет знаковое смещение в байтах с оборачиванием |
mask(self, mask: usize) -> *const T | nightly | Маскирует биты указателя согласно маске |
offset_from(self, origin: *const T) -> isize | 1.47.0 (const: 1.65.0) | Вычисляет расстояние между двумя указателями |
byte_offset_from<U>(self, origin: *const U) -> isize | 1.75.0 (const: 1.75.0) | Вычисляет расстояние в байтах между указателями |
offset_from_unsigned(self, origin: *const T) -> usize | 1.87.0 (const: 1.87.0) | Вычисляет расстояние между указателями, где self >= origin |
byte_offset_from_unsigned<U>(self, origin: *const U) -> usize | 1.87.0 (const: 1.87.0) | Вычисляет расстояние в байтах, где self >= origin |
guaranteed_eq(self, other: *const T) -> Option<bool> | nightly | Проверяет, гарантированно ли равны указатели |
guaranteed_ne(self, other: *const T) -> Option<bool> | nightly | Проверяет, гарантированно ли не равны указатели |
add(self, count: usize) -> *const T | 1.26.0 (const: 1.61.0) | Добавляет беззнаковое смещение к указателю |
byte_add(self, count: usize) -> *const T | 1.75.0 (const: 1.75.0) | Добавляет беззнаковое смещение в байтах |
sub(self, count: usize) -> *const T | 1.26.0 (const: 1.61.0) | Вычитает беззнаковое смещение из указателя |
byte_sub(self, count: usize) -> *const T | 1.75.0 (const: 1.75.0) | Вычитает беззнаковое смещение в байтах |
wrapping_add(self, count: usize) -> *const T | 1.26.0 (const: 1.61.0) | Добавляет беззнаковое смещение с оборачиванием |
wrapping_byte_add(self, count: usize) -> *const T | 1.75.0 (const: 1.75.0) | Добавляет беззнаковое смещение в байтах с оборачиванием |
wrapping_sub(self, count: usize) -> *const T | 1.26.0 (const: 1.61.0) | Вычитает беззнаковое смещение с оборачиванием |
wrapping_byte_sub(self, count: usize) -> *const T | 1.75.0 (const: 1.75.0) | Вычитает беззнаковое смещение в байтах с оборачиванием |
read(self) -> T | 1.26.0 (const: 1.71.0) | Читает значение из self, не перемещая его |
read_volatile(self) -> T | 1.26.0 | Выполняет volatile чтение значения |
read_unaligned(self) -> T | 1.26.0 (const: 1.71.0) | Читает значение из невыровненного указателя |
copy_to(self, dest: *mut T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует байты из self в dest (с перекрытием) |
copy_to_nonoverlapping(self, dest: *mut T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует байты из self в dest (без перекрытия) |
align_offset(self, align: usize) -> usize | 1.36.0 | Вычисляет смещение для выравнивания указателя |
is_aligned(self) -> bool | 1.79.0 | Проверяет, выровнен ли указатель для T |
is_aligned_to(self, align: usize) -> bool | nightly | Проверяет, выровнен ли указатель на align |
Методы для *mut T
| Метод | Версия | Описание |
|---|---|---|
is_null(self) -> bool | 1.0.0 (const: 1.84.0) | Возвращает true, если указатель нулевой |
cast<U>(self) -> *mut U | 1.38.0 (const: 1.38.0) | Приводит к указателю другого типа |
try_cast_aligned<U>(self) -> Option<*mut U> | nightly | Пытается привести к указателю другого типа с проверкой выравнивания |
with_metadata_of<U>(self, meta: *const U) -> *mut U | nightly | Использует адресное значение в новом указателе другого типа |
cast_const(self) -> *const T | 1.65.0 (const: 1.65.0) | Изменяет константность без изменения типа |
addr(self) -> usize | 1.84.0 | Получает "адресную" часть указателя |
expose_provenance(self) -> usize | 1.84.0 | Раскрывает "происхождение" указателя |
with_addr(self, addr: usize) -> *mut T | 1.84.0 | Создаёт новый указатель с заданным адресом и происхождением |
map_addr(self, f: FnOnce(usize) -> usize) -> *mut T | 1.84.0 | Создаёт новый указатель, отображая адрес на новый |
to_raw_parts(self) -> (*mut (), Metadata) | nightly | Разбирает указатель на компоненты |
as_ref<'a>(self) -> Option<&'a T> | 1.9.0 (const: 1.84.0) | Возвращает ссылку на значение или None, если null |
as_ref_unchecked<'a>(self) -> &'a T | nightly | Возвращает ссылку без проверки на null |
as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>> | nightly | Возвращает ссылку на MaybeUninit |
offset(self, count: isize) -> *mut T | 1.0.0 (const: 1.61.0) | Добавляет знаковое смещение |
byte_offset(self, count: isize) -> *mut T | 1.75.0 (const: 1.75.0) | Добавляет знаковое смещение в байтах |
wrapping_offset(self, count: isize) -> *mut T | 1.16.0 (const: 1.61.0) | Добавляет знаковое смещение с оборачиванием |
wrapping_byte_offset(self, count: isize) -> *mut T | 1.75.0 (const: 1.75.0) | Добавляет знаковое смещение в байтах с оборачиванием |
mask(self, mask: usize) -> *mut T | nightly | Маскирует биты указателя |
as_mut<'a>(self) -> Option<&'a mut T> | 1.9.0 (const: 1.84.0) | Возвращает изменяемую ссылку или None, если null |
as_mut_unchecked<'a>(self) -> &'a mut T | nightly | Возвращает изменяемую ссылку без проверки на null |
as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>> | nightly | Возвращает изменяемую ссылку на MaybeUninit |
guaranteed_eq(self, other: *mut T) -> Option<bool> | nightly | Проверяет гарантированное равенство указателей |
guaranteed_ne(self, other: *mut T) -> Option<bool> | nightly | Проверяет гарантированное неравенство указателей |
offset_from(self, origin: *const T) -> isize | 1.47.0 (const: 1.65.0) | Вычисляет расстояние между указателями |
byte_offset_from<U>(self, origin: *const U) -> isize | 1.75.0 (const: 1.75.0) | Вычисляет расстояние в байтах |
offset_from_unsigned(self, origin: *const T) -> usize | 1.87.0 (const: 1.87.0) | Вычисляет расстояние (self >= origin) |
byte_offset_from_unsigned<U>(self, origin: *mut U) -> usize | 1.87.0 (const: 1.87.0) | Вычисляет расстояние в байтах (self >= origin) |
add(self, count: usize) -> *mut T | 1.26.0 (const: 1.61.0) | Добавляет беззнаковое смещение |
byte_add(self, count: usize) -> *mut T | 1.75.0 (const: 1.75.0) | Добавляет беззнаковое смещение в байтах |
sub(self, count: usize) -> *mut T | 1.26.0 (const: 1.61.0) | Вычитает беззнаковое смещение |
byte_sub(self, count: usize) -> *mut T | 1.75.0 (const: 1.75.0) | Вычитает беззнаковое смещение в байтах |
wrapping_add(self, count: usize) -> *mut T | 1.26.0 (const: 1.61.0) | Добавляет беззнаковое смещение с оборачиванием |
wrapping_byte_add(self, count: usize) -> *mut T | 1.75.0 (const: 1.75.0) | Добавляет беззнаковое смещение в байтах с оборачиванием |
wrapping_sub(self, count: usize) -> *mut T | 1.26.0 (const: 1.61.0) | Вычитает беззнаковое смещение с оборачиванием |
wrapping_byte_sub(self, count: usize) -> *mut T | 1.75.0 (const: 1.75.0) | Вычитает беззнаковое смещение в байтах с оборачиванием |
read(self) -> T | 1.26.0 (const: 1.71.0) | Читает значение |
read_volatile(self) -> T | 1.26.0 | Выполняет volatile чтение |
read_unaligned(self) -> T | 1.26.0 (const: 1.71.0) | Читает из невыровненного указателя |
copy_to(self, dest: *mut T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует в dest (с перекрытием) |
copy_to_nonoverlapping(self, dest: *mut T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует в dest (без перекрытия) |
copy_from(self, src: *const T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует из src (с перекрытием) |
copy_from_nonoverlapping(self, src: *const T, count: usize) | 1.26.0 (const: 1.83.0) | Копирует из src (без перекрытия) |
drop_in_place(self) | 1.26.0 | Выполняет деструктор значения |
write(self, val: T) | 1.26.0 (const: 1.83.0) | Записывает значение без чтения старого |
write_bytes(self, val: u8, count: usize) | 1.26.0 (const: 1.83.0) | Заполняет память байтом (аналог memset) |
write_volatile(self, val: T) | 1.26.0 | Выполняет volatile запись |
write_unaligned(self, val: T) | 1.26.0 (const: 1.83.0) | Записывает в невыровненный указатель |
replace(self, src: T) -> T | 1.26.0 (const: 1.88.0) | Заменяет значение, возвращая старое |
swap(self, with: *mut T) | 1.26.0 (const: 1.85.0) | Меняет местами значения двух указателей |
align_offset(self, align: usize) -> usize | 1.36.0 | Вычисляет смещение для выравнивания |
is_aligned(self) -> bool | 1.79.0 | Проверяет выравнивание для T |
is_aligned_to(self, align: usize) -> bool | nightly | Проверяет выравнивание на align |
Методы для срезов *const [T] и *mut [T]
| Метод | Тип | Версия | Описание |
|---|---|---|---|
len(self) -> usize | оба | 1.79.0 (const) | Возвращает длину сырого среза |
is_empty(self) -> bool | оба | 1.79.0 (const) | Проверяет, пуст ли срез |
as_ptr(self) -> *const T | *const [T] | nightly | Возвращает указатель на буфер среза |
as_mut_ptr(self) -> *mut T | *mut [T] | nightly | Возвращает изменяемый указатель на буфер среза |
as_array<const N: usize>(self) -> Option<*const [T; N]> | *const [T] | 1.93.0 (const) | Преобразует в указатель на массив |
as_mut_array<const N: usize>(self) -> Option<*mut [T; N]> | *mut [T] | 1.93.0 (const) | Преобразует в изменяемый указатель на массив |
get_unchecked<I>(self, index: I) -> *const Output | *const [T] | nightly | Возвращает указатель на элемент без проверки границ |
get_unchecked_mut<I>(self, index: I) -> *mut Output | *mut [T] | nightly | Возвращает изменяемый указатель на элемент без проверки границ |
split_at_mut(self, mid: usize) -> (*mut [T], *mut [T]) | *mut [T] | nightly | Делит изменяемый срез на две части |
split_at_mut_unchecked(self, mid: usize) -> (*mut [T], *mut [T]) | *mut [T] | nightly | Делит изменяемый срез без проверки границ |
as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> | оба | nightly | Возвращает срез MaybeUninit (разделяемый) |
as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> | *mut [T] | nightly | Возвращает изменяемый срез MaybeUninit |
Реализации трейтов
Общие трейты для *const T и *mut T
| Трейт | *const T | *mut T | Примечания |
|---|---|---|---|
Clone | ✓ | ✓ | Возвращает дубликат значения |
Copy | ✓ | ✓ | Тип является копируемым |
Debug | ✓ | ✓ | Форматирование для отладки |
Default | ✓ | ✓ | Возвращает null() / null_mut() |
Eq | ✓ | ✓ | Равенство указателей - отношение эквивалентности |
Hash | ✓ | ✓ | Хеширование по адресу |
Ord | ✓ | ✓ | Сравнение по адресу |
PartialEq | ✓ | ✓ | Равенство по адресу |
PartialOrd | ✓ | ✓ | Сравнение по адресу |
Pointer | ✓ | ✓ | Форматирование как указатель |
!Send | ✓ | ✓ | Не является Send |
!Sync | ✓ | ✓ | Не является Sync |
Unpin | ✓ | ✓ | Является Unpin |
UnwindSafe | ✓ | ✓ | Безопасен при раскрутке стеков |
Специальные трейты
| Трейт | Для | Описание |
|---|---|---|
AtomicPrimitive | *mut T | Атомарные операции с указателями |
From<*mut T> | AtomicPtr<T> | Преобразование *mut T в AtomicPtr<T> |
CoerceUnsized | различные | Приведение размера указателей |
DispatchFromDyn | *const T, *mut T | Динамическая диспетчеризация |
Freeze | оба | Гарантирует неизменяемость |
PinCoerceUnsized | оба | Приведение размера закреплённых указателей |
VaArgSafe | оба | Безопасен для variadic функций |
Автоматические реализации трейтов
RefUnwindSafe- реализуется, когдаT: RefUnwindSafe + ?Sized
Особенности безопасности
- Большинство операций с сырыми указателями помечены как
unsafe- компилятор не может проверить их безопасность. - Проверка выравнивания - многие операции требуют правильного выравнивания указателя.
- Проверка границ - указатели должны оставаться в пределах выделенной памяти.
- Проверка на null - многие методы имеют варианты с проверкой и без проверки на null.
- Происхождение (provenance) - современные API (
addr,with_addr) учитывают происхождение указателей для строгой модели памяти.
Примеры использования
#![allow(unused)] fn main() { // Безопасное создание и использование сырых указателей let x = 42; let ptr: *const i32 = &x; unsafe { if let Some(val) = ptr.as_ref() { assert_eq!(*val, 42); } } // Арифметика указателей let arr = [1, 2, 3, 4, 5]; let ptr = arr.as_ptr(); unsafe { let ptr2 = ptr.add(2); // Указатель на третий элемент assert_eq!(*ptr2, 3); } // Работа с изменяемыми указателями let mut arr = [1, 2, 3]; let ptr = arr.as_mut_ptr(); unsafe { *ptr.add(1) = 10; // Изменяем второй элемент } assert_eq!(arr, [1, 10, 3]); }
Важно: Все операции с сырыми указателями требуют тщательного соблюдения правил безопасности Rust, включая проверку выравнивания, границ и времени жизни.
Примитивный тип reference (ссылка)
Ссылки, &T и &mut T.
Ссылка представляет заимствование некоторого владеемого значения. Вы можете получить её, используя операторы & или &mut на значении, или используя паттерны ref или ref mut.
Для тех, кто знаком с указателями, ссылка — это просто указатель, который предполагается выровненным, не нулевым и указывающим на память, содержащую допустимое значение типа T. Например, &bool может указывать только на аллокацию, содержащую целочисленные значения 1 (true) или 0 (false), но создание &bool, указывающего на аллокацию, содержащую значение 3, вызывает неопределённое поведение. Фактически, Option<&T> имеет то же представление в памяти, что и допускающий нулевое значение, но выровненный указатель, и может передаваться через границы FFI как таковой.
В большинстве случаев ссылки могут использоваться почти так же, как исходное значение. Доступ к полям, вызов методов и индексация работают одинаково (за исключением правил изменяемости, конечно). Кроме того, операторы сравнения прозрачно делегируют реализации ссылаемого значения, позволяя сравнивать ссылки так же, как владеемые значения.
Ссылки имеют прикреплённое к ним время жизни, которое представляет область действия, для которой заимствование действительно. Говорят, что время жизни "переживает" другое, если его представительная область действия равна или длиннее другой. Время жизни 'static является самым длинным временем жизни, представляющим общую продолжительность жизни программы. Например, строковые литералы имеют время жизни 'static, потому что текстовые данные встроены в двоичный файл программы, а не находятся в аллокации, которой нужно динамически управлять.
Ссылки &mut T могут быть свободно преобразованы в ссылки &T с тем же типом ссылаемого значения, а ссылки с более длинным временем жизни могут быть свободно преобразованы в ссылки с более коротким временем жизни.
PartialEq будет сравнивать значения, на которые ссылаются. Можно сравнить адрес ссылки, используя преобразование ссылка-указатель и равенство сырых указателей через ptr::eq.
#![allow(unused)] fn main() { use std::ptr; let five = 5; let other_five = 5; let five_ref = &five; let same_five_ref = &five; let other_five_ref = &other_five; assert!(five_ref == same_five_ref); assert!(five_ref == other_five_ref); assert!(ptr::eq(five_ref, same_five_ref)); assert!(!ptr::eq(five_ref, other_five_ref)); }
Для получения дополнительной информации об использовании ссылок см. раздел книги "Ссылки и заимствование".
Реализации трейтов
Трейты, реализованные для всех &T (независимо от типа ссылаемого значения):
| Трейт | Примечание |
|---|---|
Copy | |
Clone | Обратите внимание, что это не будет делегировать реализации Clone типа T, если она существует! |
Deref | |
Borrow | |
fmt::Pointer |
Трейты для &mut T (независимо от типа ссылаемого значения):
Получает все вышеперечисленные трейты, кроме Copy и Clone (чтобы предотвратить создание нескольких одновременных изменяемых заимствований), плюс:
| Трейт | Описание |
|---|---|
DerefMut | |
BorrowMut |
Трейты, реализованные для &T, если базовый T также реализует этот трейт:
| Трейт | Примечание |
|---|---|
Все трейты в std::fmt, кроме fmt::Pointer (который реализован независимо от типа ссылаемого значения) и fmt::Write | |
PartialOrd | |
Ord | |
PartialEq | |
Eq | |
AsRef | |
Fn | Кроме того, &T получает FnMut и FnOnce, если T: Fn |
Hash | |
ToSocketAddrs | |
Sync |
Трейты для &mut T, если T реализует этот трейт:
Получает все вышеперечисленные трейты, кроме ToSocketAddrs, плюс:
| Трейт | Примечание |
|---|---|
AsMut | |
FnMut | Кроме того, &mut T получает FnOnce, если T: FnMut |
fmt::Write | |
Iterator | |
DoubleEndedIterator | |
ExactSizeIterator | |
FusedIterator | |
TrustedLen | |
Send | |
io::Write | |
Read | |
Seek | |
BufRead |
Кроме того, ссылки &T реализуют Send тогда и только тогда, когда T реализует Sync.
Примечание: Из-за приведения разыменования при вызове метода просто вызов метода трейта будет работать как со ссылками, так и с владеемыми значениями! Описанные здесь реализации предназначены для общих контекстов, где окончательный тип T является параметром типа или иным образом неизвестен локально.
Безопасность
Для всех типов T: ?Sized и для всех t: &T или t: &mut T, когда такие значения пересекают границу API, обычно должны соблюдаться следующие инварианты:
| Инвариант | Описание |
|---|---|
t не нулевой | |
t выровнен по align_of_val(t) | |
если size_of_val(t) > 0, то t разыменовываем для size_of_val(t) байтов |
Если t указывает на адрес a, "разыменовываемость" для N байтов означает, что диапазон памяти [a, a + N) полностью содержится в одной аллокации.
Например, это означает, что небезопасный код в безопасной функции может предполагать, что эти инварианты обеспечены для аргументов, переданных вызывающей стороной, и он может предполагать, что эти инварианты обеспечены для возвращаемых значений любых безопасных функций, которые он вызывает.
Для обратного направления всё сложнее: когда небезопасный код передаёт аргументы в безопасные функции или возвращает значения из безопасных функций, они обычно должны как минимум не нарушать эти инварианты. Полные требования сильнее, поскольку ссылка обычно должна указывать на данные, которые безопасно использовать как тип T.
Ещё не решено, может ли небезопасный код временно нарушать эти инварианты на внутренних данных. Как следствие, небезопасный код, который временно нарушает эти инварианты на внутренних данных, может быть незвуковым или стать незвуковым в будущих версиях Rust в зависимости от того, как будет решён этот вопрос.
Таблицы реализаций трейтов
Реализации PartialEq
| Тип | Реализация |
|---|---|
impl<A, B> PartialEq<&B> for &A where A: PartialEq<B> + ?Sized, B: ?Sized | fn eq(&self, other: &&B) -> bool |
impl<A, B> PartialEq<&B> for &mut A where A: PartialEq<B> + ?Sized, B: ?Sized | fn eq(&self, other: &&B) -> bool |
impl<A, B> PartialEq<&mut B> for &A where A: PartialEq<B> + ?Sized, B: ?Sized | fn eq(&self, other: &&mut B) -> bool |
impl<A, B> PartialEq<&mut B> for &mut A where A: PartialEq<B> + ?Sized, B: ?Sized | fn eq(&self, other: &&mut B) -> bool |
Реализации PartialOrd
| Тип | Реализация |
|---|---|
impl<A, B> PartialOrd<&B> for &A where A: PartialOrd<B> + ?Sized, B: ?Sized | fn partial_cmp(&self, other: &&B) -> Option<Ordering> |
impl<A, B> PartialOrd<&mut B> for &mut A where A: PartialOrd<B> + ?Sized, B: ?Sized | fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> |
Реализации CoerceUnsized
| Тип | Реализация |
|---|---|
impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T where 'b: 'a, T: Unsize<U> + ?Sized, U: ?Sized | |
impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b mut T where 'b: 'a, T: Unsize<U> + ?Sized, U: ?Sized | |
impl<'a, T, U> CoerceUnsized<&'a mut U> for &'a mut T where T: Unsize<U> + ?Sized, U: ?Sized |
Реализации DispatchFromDyn
| Тип | Реализация |
|---|---|
impl<'a, T, U> DispatchFromDyn<&'a U> for &'a T where T: Unsize<U> + ?Sized, U: ?Sized | |
impl<'a, T, U> DispatchFromDyn<&'a mut U> for &'a mut T where T: Unsize<U> + ?Sized, U: ?Sized |
Сводная таблица методов
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | fn eq(&self, other: &&B) -> bool | Проверяет равенство значений self и other |
| 1.0.0 | fn ne(&self, other: &&B) -> bool | Проверяет неравенство значений self и other |
| 1.0.0 | fn partial_cmp(&self, other: &&B) -> Option<Ordering> | Возвращает упорядочивание между self и other, если оно существует |
| 1.0.0 | fn lt(&self, other: &&B) -> bool | Проверяет, меньше ли self, чем other |
| 1.0.0 | fn le(&self, other: &&B) -> bool | Проверяет, меньше или равен ли self, чем other |
| 1.0.0 | fn gt(&self, other: &&B) -> bool | Проверяет, больше ли self, чем other |
| 1.0.0 | fn ge(&self, other: &&B) -> bool | Проверяет, больше или равен ли self, чем other |
Примитивный тип slice
Динамически изменяемое представление непрерывной последовательности [T].
Непрерывный здесь означает, что элементы расположены так, что каждый элемент находится на одинаковом расстоянии от своих соседей.
Смотрите также модуль std::slice.
Срезы (slices) представляют собой вид на блок памяти, представленный как указатель и длина.
#![allow(unused)] fn main() { // создание среза из Vec let vec = vec![1, 2, 3]; let int_slice = &vec[..]; // приведение массива к срезу let str_slice: &[&str] = &["one", "two", "three"]; }
Срезы могут быть либо изменяемыми, либо общими (разделяемыми). Общий тип среза - &[T], тогда как изменяемый тип среза - &mut [T], где T представляет тип элемента. Например, вы можете изменять блок памяти, на который указывает изменяемый срез:
#![allow(unused)] fn main() { let mut x = [1, 2, 3]; let x = &mut x[..]; // Берём полный срез `x`. x[1] = 7; assert_eq!(x, &[1, 7, 3]); }
Можно создавать пустые поддиапазоны срезов, используя пустые диапазоны (включая slice.len()..slice.len()):
#![allow(unused)] fn main() { let x = [1, 2, 3]; let empty = &x[0..0]; // подсрез перед первым элементом assert_eq!(empty, &[]); let empty = &x[..0]; // то же, что &x[0..0] assert_eq!(empty, &[]); let empty = &x[1..1]; // пустой подсрез в середине assert_eq!(empty, &[]); let empty = &x[3..3]; // подсрез после последнего элемента assert_eq!(empty, &[]); let empty = &x[3..]; // то же, что &x[3..3] assert_eq!(empty, &[]); }
Не допускается использование поддиапазонов, которые начинаются с нижней границы, большей чем slice.len():
ⓘ
#![allow(unused)] fn main() { let x = vec![1, 2, 3]; let _ = &x[4..4]; }
Поскольку срезы хранят длину последовательности, на которую они ссылаются, они имеют вдвое больший размер, чем указатели на типы с известным размером (Sized types). Смотрите также справочник по динамически изменяемым типам (dynamically sized types).
#![allow(unused)] fn main() { let pointer_size = size_of::<&u8>(); assert_eq!(2 * pointer_size, size_of::<&[u8]>()); assert_eq!(2 * pointer_size, size_of::<*const [u8]>()); assert_eq!(2 * pointer_size, size_of::<Box<[u8]>>()); assert_eq!(2 * pointer_size, size_of::<Rc<[u8]>>()); }
Реализации трейтов
Некоторые трейты реализованы для срезов, если тип элемента реализует этот трейт. Это включает Eq, Hash и Ord.
Итерация
Срезы реализуют IntoIterator. Итератор возвращает ссылки на элементы среза.
#![allow(unused)] fn main() { let numbers: &[i32] = &[0, 1, 2]; for n in numbers { println!("{n} is a number!"); } }
Изменяемый срез возвращает изменяемые ссылки на элементы:
#![allow(unused)] fn main() { let mut scores: &mut [i32] = &mut [7, 8, 9]; for score in scores { *score += 1; } }
Этот итератор возвращает изменяемые ссылки на элементы среза, поэтому, хотя тип элемента среза - i32, тип элемента итератора - &mut i32.
.iterи.iter_mut- явные методы для возврата итераторов по умолчанию.- Другие методы, возвращающие итераторы:
.split,.splitn,.chunks,.windowsи другие.
Таблицы методов
Методы Box<[T]>
| Версия | Метод | Описание |
|---|---|---|
| 1.82.0 | pub fn new_uninit_slice(len: usize) -> Box<[MaybeUninit<T>]> | Создаёт новый упакованный срез с неинициализированным содержимым |
| 1.92.0 | pub fn new_zeroed_slice(len: usize) -> Box<[MaybeUninit<T>]> | Создаёт новый упакованный срез с неинициализированным содержимым, память заполнена 0 байтами |
| 🔬 | pub fn try_new_uninit_slice(len: usize) -> Result<Box<[MaybeUninit<T>]>, AllocError> | Создаёт новый упакованный срез с неинициализированным содержимым, возвращает ошибку при неудачном выделении |
| 🔬 | pub fn try_new_zeroed_slice(len: usize) -> Result<Box<[MaybeUninit<T>]>, AllocError> | Создаёт новый упакованный срез с неинициализированным содержимым, память заполнена 0 байтами, возвращает ошибку при неудачном выделении |
| 🔬 | pub fn into_array<const N: usize>(self) -> Option<Box<[T; N]>> | Преобразует упакованный срез в упакованный массив |
Методы Box<[T], A> (с аллокатором)
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[MaybeUninit<T>], A> | Создаёт новый упакованный срез с неинициализированным содержимым в предоставленном аллокаторе |
| 🔬 | pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[MaybeUninit<T>], A> | Создаёт новый упакованный срез с неинициализированным содержимым в предоставленном аллокаторе, память заполнена 0 байтами |
| 🔬 | pub fn try_new_uninit_slice_in(len: usize, alloc: A) -> Result<Box<[MaybeUninit<T>], A>, AllocError> | Создаёт новый упакованный срез с неинициализированным содержимым в предоставленном аллокаторе, возвращает ошибку при неудачном выделении |
| 🔬 | pub fn try_new_zeroed_slice_in(len: usize, alloc: A) -> Result<Box<[MaybeUninit<T>], A>, AllocError> | Создаёт новый упакованный срез с неинициализированным содержимым в предоставленном аллокаторе, память заполнена 0 байтами, возвращает ошибку при неудачном выделении |
Методы Box<[MaybeUninit<T>], A>
| Версия | Метод | Описание |
|---|---|---|
| 1.82.0 | pub unsafe fn assume_init(self) -> Box<[T], A> | Преобразует в Box<[T], A> |
Методы [MaybeUninit<T>]
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub const fn write_copy_of_slice(&mut self, src: &[T]) -> &mut [T] where T: Copy | Копирует элементы из src в self, возвращает изменяемую ссылку на теперь инициализированное содержимое |
| 🔬 | pub fn write_clone_of_slice(&mut self, src: &[T]) -> &mut [T] where T: Clone | Клонирует элементы из src в self, возвращает изменяемую ссылку на теперь инициализированное содержимое |
| 🔬 | pub fn write_filled(&mut self, value: T) -> &mut [T] where T: Clone | Заполняет срез элементами путём клонирования значения |
| 🔬 | pub fn write_with<F>(&mut self, f: F) -> &mut [T] where F: FnMut(usize) -> T | Заполняет срез элементами, возвращаемыми вызовом замыкания для каждого индекса |
| 🔬 | pub fn write_iter<I>(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit<T>]) where I: IntoIterator<Item = T> | Заполняет срез элементами, полученными от итератора |
| 🔬 | pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] | Возвращает содержимое этого MaybeUninit как срез потенциально неинициализированных байтов |
| 🔬 | pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] | Возвращает содержимое этого MaybeUninit как изменяемый срез потенциально неинициализированных байтов |
| 🔬 | pub const unsafe fn assume_init_drop(&mut self) | Уничтожает содержащиеся значения на месте |
| 🔬 | pub const unsafe fn assume_init_ref(&self) -> &[T] | Получает общую ссылку на содержащееся значение |
| 🔬 | pub const unsafe fn assume_init_mut(&mut self) -> &mut [T] | Получает изменяемую (уникальную) ссылку на содержащееся значение |
Методы [AsciiChar]
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub const fn as_str(&self) -> &str | Просматривает этот срез ASCII символов как UTF-8 str |
| 🔬 | pub const fn as_bytes(&self) -> &[u8] | Просматривает этот срез ASCII символов как срез байтов u8 |
Методы [u8]
| Версия | Метод | Описание |
|---|---|---|
| 1.23.0 | pub const fn is_ascii(&self) -> bool | Проверяет, находятся ли все байты в этом срезе в диапазоне ASCII |
| 🔬 | pub const fn as_ascii(&self) -> Option<&[AsciiChar]> | Если этот срез is_ascii, возвращает его как срез ASCII символов, иначе None |
| 🔬 | pub const unsafe fn as_ascii_unchecked(&self) -> &[AsciiChar] | Преобразует этот срез байтов в срез ASCII символов без проверки их валидности |
| 1.23.0 | pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool | Проверяет, являются ли два среза совпадающими без учёта регистра ASCII |
| 1.23.0 | pub const fn make_ascii_uppercase(&mut self) | Преобразует этот срез в эквивалент в верхнем регистре ASCII на месте |
| 1.23.0 | pub const fn make_ascii_lowercase(&mut self) | Преобразует этот срез в эквивалент в нижнем регистре ASCII на месте |
| 1.60.0 | pub fn escape_ascii(&self) -> EscapeAscii<'_> | Возвращает итератор, который создаёт экранированную версию этого среза, рассматривая его как ASCII строку |
| 1.80.0 | pub const fn trim_ascii_start(&self) -> &[u8] | Возвращает срез байтов с удалёнными ведущими ASCII пробельными байтами |
| 1.80.0 | pub const fn trim_ascii_end(&self) -> &[u8] | Возвращает срез байтов с удалёнными завершающими ASCII пробельными байтами |
| 1.80.0 | pub const fn trim_ascii(&self) -> &[u8] | Возвращает срез байтов с удалёнными ведущими и завершающими ASCII пробельными байтами |
Основные методы [T]
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub const fn len(&self) -> usize | Возвращает количество элементов в срезе |
| 1.0.0 | pub const fn is_empty(&self) -> bool | Возвращает true, если длина среза равна 0 |
| 1.0.0 | pub const fn first(&self) -> Option<&T> | Возвращает первый элемент среза или None, если он пуст |
| 1.0.0 | pub const fn first_mut(&mut self) -> Option<&mut T> | Возвращает изменяемую ссылку на первый элемент среза или None, если он пуст |
| 1.5.0 | pub const fn split_first(&self) -> Option<(&T, &[T])> | Возвращает первый и все остальные элементы среза |
| 1.5.0 | pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> | Возвращает первый и все остальные элементы среза (изменяемые) |
| 1.5.0 | pub const fn split_last(&self) -> Option<(&T, &[T])> | Возвращает последний и все остальные элементы среза |
| 1.5.0 | pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> | Возвращает последний и все остальные элементы среза (изменяемые) |
| 1.0.0 | pub const fn last(&self) -> Option<&T> | Возвращает последний элемент среза или None, если он пуст |
| 1.0.0 | pub const fn last_mut(&mut self) -> Option<&mut T> | Возвращает изменяемую ссылку на последний элемент среза или None, если он пуст |
Методы для чанков и окон
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn iter(&self) -> Iter<'_, T> | Возвращает итератор по срезу |
| 1.0.0 | pub fn iter_mut(&mut self) -> IterMut<'_, T> | Возвращает итератор, позволяющий изменять каждое значение |
| 1.0.0 | pub fn windows(&self, size: usize) -> Windows<'_, T> | Возвращает итератор по всем смежным окнам длины size |
| 1.0.0 | pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> | Возвращает итератор по chunk_size элементам среза за раз |
| 1.0.0 | pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> | Возвращает итератор по chunk_size элементам среза за раз (изменяемые) |
| 1.31.0 | pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> | Возвращает итератор по chunk_size элементам среза за раз (точные чанки) |
| 1.31.0 | pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> | Возвращает итератор по chunk_size элементам среза за раз (точные чанки, изменяемые) |
| 1.31.0 | pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> | Возвращает итератор по chunk_size элементам среза за раз, начиная с конца |
| 1.31.0 | pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> | Возвращает итератор по chunk_size элементам среза за раз, начиная с конца (изменяемые) |
| 1.31.0 | pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> | Возвращает итератор по chunk_size элементам среза за раз, начиная с конца (точные чанки) |
| 1.31.0 | pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> | Возвращает итератор по chunk_size элементам среза за раз, начиная с конца (точные чанки, изменяемые) |
Методы для работы с индексами и указателями
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[T]>>::Output> where I: SliceIndex<[T]> | Возвращает ссылку на элемент или подсрез в зависимости от типа индекса |
| 1.0.0 | pub fn get_mut<I>(&mut self, index: I) -> Option<&mut <I as SliceIndex<[T]>>::Output> where I: SliceIndex<[T]> | Возвращает изменяемую ссылку на элемент или подсрез |
| 1.0.0 | pub unsafe fn get_unchecked<I>(&self, index: I) -> &<I as SliceIndex<[T]>>::Output where I: SliceIndex<[T]> | Возвращает ссылку на элемент или подсрез без проверки границ |
| 1.0.0 | pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut <I as SliceIndex<[T]>>::Output where I: SliceIndex<[T]> | Возвращает изменяемую ссылку на элемент или подсрез без проверки границ |
| 1.0.0 | pub const fn as_ptr(&self) -> *const T | Возвращает необработанный указатель на буфер среза |
| 1.0.0 | pub const fn as_mut_ptr(&mut self) -> *mut T | Возвращает небезопасный изменяемый указатель на буфер среза |
| 1.48.0 | pub const fn as_ptr_range(&self) -> Range<*const T> | Возвращает два необработанных указателя, охватывающих срез |
| 1.48.0 | pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> | Возвращает два небезопасных изменяемых указателя, охватывающих срез |
| 1.93.0 | pub const fn as_array<const N: usize>(&self) -> Option<&[T; N]> | Получает ссылку на базовый массив |
| 1.93.0 | pub const fn as_mut_array<const N: usize>(&mut self) -> Option<&mut [T; N]> | Получает изменяемую ссылку на базовый массив среза |
Методы манипуляции с элементами
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub const fn swap(&mut self, a: usize, b: usize) | Меняет местами два элемента в срезе |
| 🔬 | pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) | Меняет местами два элемента в срезе без проверки границ |
| 1.0.0 | pub const fn reverse(&mut self) | Изменяет порядок элементов в срезе на противоположный на месте |
Методы разделения срезов
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub const fn split_at(&self, mid: usize) -> (&[T], &[T]) | Делит один срез на два по индексу |
| 1.0.0 | pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) | Делит один изменяемый срез на два по индексу |
| 1.79.0 | pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) | Делит один срез на два по индексу без проверки границ |
| 1.79.0 | pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) | Делит один изменяемый срез на два по индексу без проверки границ |
| 1.80.0 | pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> | Делит один срез на два по индексу, возвращает None если срез слишком короткий |
| 1.80.0 | pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> | Делит один изменяемый срез на два по индексу, возвращает None если срез слишком короткий |
| 1.0.0 | pub fn split<F>(&self, pred: F) -> Split<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по подрезам, разделённым элементами, которые соответствуют pred |
| 1.0.0 | pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по изменяемым подрезам, разделённым элементами, которые соответствуют pred |
| 1.51.0 | pub fn split_inclusive<F>(&self, pred: F) -> SplitInclusive<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по подрезам, разделённым элементами, которые соответствуют pred, включая разделитель в конец предыдущего подреза |
| 1.51.0 | pub fn split_inclusive_mut<F>(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по изменяемым подрезам, разделённым элементами, которые соответствуют pred, включая разделитель |
| 1.27.0 | pub fn rsplit<F>(&self, pred: F) -> RSplit<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по подрезам, разделённым элементами, которые соответствуют pred, начиная с конца среза |
| 1.27.0 | pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по изменяемым подрезам, разделённым элементами, которые соответствуют pred, начиная с конца среза |
| 1.0.0 | pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по подрезам, разделённым элементами, которые соответствуют pred, ограниченный возвратом не более n элементов |
| 1.0.0 | pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по изменяемым подрезам, разделённым элементами, которые соответствуют pred, ограниченный возвратом не более n элементов |
| 1.0.0 | pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по подрезам, разделённым элементами, которые соответствуют pred, ограниченный возвратом не более n элементов, начиная с конца |
| 1.0.0 | pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<'_, T, F> where F: FnMut(&T) -> bool | Возвращает итератор по изменяемым подрезам, разделённым элементами, которые соответствуют pred, ограниченный возвратом не более n элементов, начиная с конца |
| 🔬 | pub fn split_once<F>(&self, pred: F) -> Option<(&[T], &[T])> where F: FnMut(&T) -> bool | Разделяет срез на первом элементе, который соответствует указанному предикату |
| 🔬 | pub fn rsplit_once<F>(&self, pred: F) -> Option<(&[T], &[T])> where F: FnMut(&T) -> bool | Разделяет срез на последнем элементе, который соответствует указанному предикату |
Методы поиска и сравнения
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn contains(&self, x: &T) -> bool where T: PartialEq | Возвращает true, если срез содержит элемент с заданным значением |
| 1.0.0 | pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq | Возвращает true, если needle является префиксом среза |
| 1.0.0 | pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq | Возвращает true, если needle является суффиксом среза |
| 1.51.0 | pub fn strip_prefix<P>(&self, prefix: &P) -> Option<&[T]> where P: SlicePattern<Item = T> + ?Sized, T: PartialEq | Возвращает подсрез с удалённым префиксом |
| 1.51.0 | pub fn strip_suffix<P>(&self, suffix: &P) -> Option<&[T]> where P: SlicePattern<Item = T> + ?Sized, T: PartialEq | Возвращает подсрез с удалённым суффиксом |
| 🔬 | pub fn strip_circumfix<S, P>(&self, prefix: &P, suffix: &S) -> Option<&[T]> where T: PartialEq, S: SlicePattern<Item = T> + ?Sized, P: SlicePattern<Item = T> + ?Sized | Возвращает подсрез с удалёнными префиксом и суффиксом |
| 🔬 | pub fn trim_prefix<P>(&self, prefix: &P) -> &[T] where P: SlicePattern<Item = T> + ?Sized, T: PartialEq | Возвращает подсрез с опционально удалённым префиксом |
| 🔬 | pub fn trim_suffix<P>(&self, suffix: &P) -> &[T] where P: SlicePattern<Item = T> + ?Sized, T: PartialEq | Возвращает подсрез с опционально удалённым суффиксом |
Методы бинарного поиска
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord | Бинарно ищет в этом срезе заданный элемент |
| 1.0.0 | pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize> where F: FnMut(&'a T) -> Ordering | Бинарно ищет в этом срезе с функцией-компаратором |
| 1.10.0 | pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize> where F: FnMut(&'a T) -> B, B: Ord | Бинарно ищет в этом срезе с функцией извлечения ключа |
| 1.52.0 | pub fn partition_point<P>(&self, pred: P) -> usize where P: FnMut(&T) -> bool | Возвращает индекс точки раздела согласно заданному предикату |
Методы сортировки
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn sort(&mut self) where T: Ord | Сортирует срез в возрастающем порядке, сохраняя начальный порядок равных элементов (стабильная сортировка) |
| 1.0.0 | pub fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering | Сортирует срез в возрастающем порядке с функцией сравнения, сохраняя начальный порядок равных элементов |
| 1.7.0 | pub fn sort_by_key<K, F>(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord | Сортирует срез в возрастающем порядке с функцией извлечения ключа, сохраняя начальный порядок равных элементов |
| 1.34.0 | pub fn sort_by_cached_key<K, F>(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord | Сортирует срез в возрастающем порядке с функцией извлечения ключа, сохраняя начальный порядок равных элементов (с кэшированием ключей) |
| 1.20.0 | pub fn sort_unstable(&mut self) where T: Ord | Сортирует срез в возрастающем порядке без сохранения начального порядка равных элементов (нестабильная сортировка) |
| 1.20.0 | pub fn sort_unstable_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering | Сортирует срез в возрастающем порядке с функцией сравнения без сохранения начального порядка равных элементов |
| 1.20.0 | pub fn sort_unstable_by_key<K, F>(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord | Сортирует срез в возрастающем порядке с функцией извлечения ключа без сохранения начального порядка равных элементов |
Методы выбора элементов
| Версия | Метод | Описание |
|---|---|---|
| 1.49.0 | pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T]) where T: Ord | Переупорядочивает срез так, чтобы элемент по индексу находился в позиции порядка сортировки |
| 1.49.0 | pub fn select_nth_unstable_by<F>(&mut self, index: usize, compare: F) -> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> Ordering | Переупорядочивает срез с функцией-компаратором так, чтобы элемент по индексу находился в позиции порядка сортировки |
| 1.49.0 | pub fn select_nth_unstable_by_key<K, F>(&mut self, index: usize, f: F) -> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T) -> K, K: Ord | Переупорядочивает срез с функцией извлечения ключа так, чтобы элемент по индексу находился в позиции порядка сортировки |
Методы работы с дубликатами
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub fn partition_dedup(&mut self) -> (&mut [T], &mut [T]) where T: PartialEq | Перемещает все последовательные повторяющиеся элементы в конец среза согласно реализации PartialEq |
| 🔬 | pub fn partition_dedup_by<F>(&mut self, same_bucket: F) -> (&mut [T], &mut [T]) where F: FnMut(&mut T, &mut T) -> bool | Перемещает все, кроме первого, последовательных элементов в конец среза, удовлетворяющих заданному отношению равенства |
| 🔬 | pub fn partition_dedup_by_key<K, F>(&mut self, key: F) -> (&mut [T], &mut [T]) where F: FnMut(&mut T) -> K, K: PartialEq | Перемещает все, кроме первого, последовательных элементов в конец среза, которые разрешаются в один и тот же ключ |
Методы вращения
| Версия | Метод | Описание |
|---|---|---|
| 1.26.0 | pub const fn rotate_left(&mut self, mid: usize) | Вращает срез на месте так, что первые mid элементов среза перемещаются в конец |
| 1.26.0 | pub const fn rotate_right(&mut self, k: usize) | Вращает срез на месте так, что первые self.len() - k элементов среза перемещаются в конец |
Методы заполнения и копирования
| Версия | Метод | Описание |
|---|---|---|
| 1.50.0 | pub fn fill(&mut self, value: T) where T: Clone | Заполняет self элементами путём клонирования значения |
| 1.51.0 | pub fn fill_with<F>(&mut self, f: F) where F: FnMut() -> T | Заполняет self элементами, возвращаемыми при многократном вызове замыкания |
| 1.7.0 | pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone | Копирует элементы из src в self |
| 1.9.0 | pub const fn copy_from_slice(&mut self, src: &[T]) where T: Copy | Копирует все элементы из src в self, используя memcpy |
| 1.37.0 | pub fn copy_within<R>(&mut self, src: R, dest: usize) where R: RangeBounds<usize>, T: Copy | Копирует элементы из одной части среза в другую часть самого себя, используя memmove |
| 1.27.0 | pub fn swap_with_slice(&mut self, other: &mut [T]) | Меняет местами все элементы в self с теми, что в other |
Методы преобразования типов
| Версия | Метод | Описание |
|---|---|---|
| 1.30.0 | pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) | Преобразует срез в срез другого типа, обеспечивая сохранение выравнивания типов |
| 1.30.0 | pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) | Преобразует изменяемый срез в изменяемый срез другого типа, обеспечивая сохранение выравнивания типов |
| 🔬 | pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]) where Simd<T, LANES>: AsRef<[T; LANES]>, T: SimdElement, LaneCount<LANES>: SupportedLaneCount | Разделяет срез на префикс, середину из выровненных SIMD типов и суффикс |
| 🔬 | pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]) where Simd<T, LANES>: AsMut<[T; LANES]>, T: SimdElement, LaneCount<LANES>: SupportedLaneCount | Разделяет изменяемый срез на изменяемый префикс, середину из выровненных SIMD типов и изменяемый суффикс |
Методы проверки отсортированности
| Версия | Метод | Описание |
|---|---|---|
| 1.82.0 | pub fn is_sorted(&self) -> bool where T: PartialOrd | Проверяет, отсортированы ли элементы этого среза |
| 1.82.0 | pub fn is_sorted_by<'a, F>(&'a self, compare: F) -> bool where F: FnMut(&'a T, &'a T) -> bool | Проверяет, отсортированы ли элементы этого среза, используя заданную функцию-компаратор |
| 1.82.0 | pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool where F: FnMut(&'a T) -> K, K: PartialOrd | Проверяет, отсортированы ли элементы этого среза, используя заданную функцию извлечения ключа |
Методы разделения с отрезанием
| Версия | Метод | Описание |
|---|---|---|
| 1.87.0 | pub fn split_off<'a, R>(self: &mut &'a [T], range: R) -> Option<&'a [T]> where R: OneSidedRange<usize> | Удаляет подсрез, соответствующий заданному диапазону, и возвращает ссылку на него |
| 1.87.0 | pub fn split_off_mut<'a, R>(self: &mut &'a mut [T], range: R) -> Option<&'a mut [T]> where R: OneSidedRange<usize> | Удаляет подсрез, соответствующий заданному диапазону, и возвращает изменяемую ссылку на него |
| 1.87.0 | pub fn split_off_first<'a>(self: &mut &'a [T]) -> Option<&'a T> | Удаляет первый элемент среза и возвращает ссылку на него |
| 1.87.0 | pub fn split_off_first_mut<'a>(self: &mut &'a mut [T]) -> Option<&'a mut T> | Удаляет первый элемент среза и возвращает изменяемую ссылку на него |
| 1.87.0 | pub fn split_off_last<'a>(self: &mut &'a [T]) -> Option<&'a T> | Удаляет последний элемент среза и возвращает ссылку на него |
| 1.87.0 | pub fn split_off_last_mut<'a>(self: &mut &'a mut [T]) -> Option<&'a mut T> | Удаляет последний элемент среза и возвращает изменяемую ссылку на него |
Методы для работы с несколькими индексами
| Версия | Метод | Описание |
|---|---|---|
| 1.86.0 | pub unsafe fn get_disjoint_unchecked_mut<I, const N: usize>(&mut self, indices: [I; N]) -> [&mut <I as SliceIndex<[T]>>::Output; N] where I: GetDisjointMutIndex + SliceIndex<[T]> | Возвращает изменяемые ссылки на многие индексы одновременно без каких-либо проверок |
| 1.86.0 | pub fn get_disjoint_mut<I, const N: usize>(&mut self, indices: [I; N]) -> Result<[&mut <I as SliceIndex<[T]>>::Output; N], GetDisjointMutError> where I: GetDisjointMutIndex + SliceIndex<[T]> | Возвращает изменяемые ссылки на многие индексы одновременно |
Методы для работы со смещениями
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub fn element_offset(&self, element: &T) -> Option<usize> | Возвращает индекс, на который указывает ссылка на элемент |
| 🔬 | pub fn subslice_range(&self, subslice: &[T]) -> Option<Range<usize>> | Возвращает диапазон индексов, на которые указывает подсрез |
Методы [MaybeUninit<T>] - дополнительное выравнивание
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub fn align_to_uninit_mut<U>(&mut self) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<U>], &mut [MaybeUninit<T>]) | Преобразует неинициализированный изменяемый срез в неинициализированный изменяемый срез другого типа, обеспечивая сохранение выравнивания |
Методы [[T; N]] (срезы массивов)
| Версия | Метод | Описание |
|---|---|---|
| 1.80.0 | pub const fn as_flattened(&self) -> &[T] | Берёт &[[T; N]] и преобразует его в &[T] |
| 1.80.0 | pub const fn as_flattened_mut(&mut self) -> &mut [T] | Берёт &mut [[T; N]] и преобразует его в &mut [T] |
Методы [f32] и [f64]
| Версия | Метод | Описание |
|---|---|---|
| 🔬 | pub fn sort_floats(&mut self) | Сортирует срез чисел с плавающей запятой |
Метод [u8] для работы с UTF-8
| Версия | Метод | Описание |
|---|---|---|
| 1.79.0 | pub fn utf8_chunks(&self) -> Utf8Chunks<'_> | Создаёт итератор по смежным допустимым диапазонам UTF-8 этого среза и фрагментам не-UTF-8 между ними |
Методы преобразования в векторы
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn to_vec(&self) -> Vec<T> where T: Clone | Копирует self в новый Vec |
| 🔬 | pub fn to_vec_in<A>(&self, alloc: A) -> Vec<T, A> where A: Allocator, T: Clone | Копирует self в новый Vec с аллокатором |
| 1.0.0 | pub fn into_vec<A>(self: Box<[T], A>) -> Vec<T, A> where A: Allocator | Преобразует self в вектор без клонирования или выделения памяти |
| 1.40.0 | pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy | Создаёт вектор, копируя срез n раз |
Методы объединения и соединения
| Версия | Метод | Описание |
|---|---|---|
| 1.0.0 | pub fn concat<Item>(&self) -> <[T] as Concat<Item>>::Output where [T]: Concat<Item>, Item: ?Sized | Преобразует срез T в единое значение Self::Output |
| 1.3.0 | pub fn join<Separator>(&self, sep: Separator) -> <[T] as Join<Separator>>::Output where [T]: Join<Separator> | Преобразует срез T в единое значение Self::Output, размещая заданный разделитель между каждым |
| 1.0.0 | pub fn connect<Separator>(&self, sep: Separator) -> <[T] as Join<Separator>>::Output where [T]: Join<Separator> | Устаревший аналог join |
Методы преобразования регистра ASCII для [u8]
| Версия | Метод | Описание |
|---|---|---|
| 1.23.0 | pub fn to_ascii_uppercase(&self) -> Vec<u8> | Возвращает вектор, содержащий копию этого среза, где каждый байт отображён в его эквивалент в верхнем регистре ASCII |
| 1.23.0 | pub fn to_ascii_lowercase(&self) -> Vec<u8> | Возвращает вектор, содержащий копию этого среза, где каждый байт отображён в его эквивалент в нижнем регистре ASCII |
Реализации трейтов
Трейт AsMut
| Тип | Реализация |
|---|---|
impl<T> AsMut<[T]> for [T] | fn as_mut(&mut self) -> &mut [T] |
impl<T, const N: usize> AsMut<[T]> for [T; N] | fn as_mut(&mut self) -> &mut [T] |
impl<T, const N: usize> AsMut<[T]> for Simd<T, N> where LaneCount<N>: SupportedLaneCount, T: SimdElement | fn as_mut(&mut self) -> &mut [T] |
impl<T, A> AsMut<[T]> for Vec<T, A> where A: Allocator | fn as_mut(&mut self) -> &mut [T] |
impl AsMut<[u8]> for ByteStr | fn as_mut(&mut self) -> &mut [u8] |
impl AsMut<[u8]> for ByteString | fn as_mut(&mut self) -> &mut [u8] |
Трейт AsRef
| Тип | Реализация |
|---|---|
impl<T> AsRef<[T]> for [T] | fn as_ref(&self) -> &[T] |
impl<T, const N: usize> AsRef<[T]> for [T; N] | fn as_ref(&self) -> &[T] |
impl<'a, T, A> AsRef<[T]> for Drain<'a, T, A> where A: Allocator | fn as_ref(&self) -> &[T] |
impl<T, A> AsRef<[T]> for IntoIter<T, A> where A: Allocator | fn as_ref(&self) -> &[T] |
impl<T> AsRef<[T]> for Iter<'_, T> | fn as_ref(&self) -> &[T] |
impl<T> AsRef<[T]> for IterMut<'_, T> | fn as_ref(&self) -> &[T] |
impl<T, const N: usize> AsRef<[T]> for Simd<T, N> where LaneCount<N>: SupportedLaneCount, T: SimdElement | fn as_ref(&self) -> &[T] |
impl<T, A> AsRef<[T]> for Vec<T, A> where A: Allocator | fn as_ref(&self) -> &[T] |
impl AsRef<[u8]> for ByteStr | fn as_ref(&self) -> &[u8] |
impl AsRef<[u8]> for ByteString | fn as_ref(&self) -> &[u8] |
impl<'a> AsRef<[u8]> for Drain<'a> | fn as_ref(&self) -> &[u8] |
impl AsRef<[u8]> for String | fn as_ref(&self) -> &[u8] |
impl AsRef<[u8]> for str | fn as_ref(&self) -> &[u8] |
Устаревший трейт AsciiExt
| Тип | Реализация |
|---|---|
impl AsciiExt for [u8] | type Owned = Vec<u8> |
Трейт Borrow
| Тип | Реализация |
|---|---|
impl<T, const N: usize> Borrow<[T]> for [T; N] | fn borrow(&self) -> &[T] |
impl<T, A> Borrow<[T]> for Vec<T, A> where A: Allocator | fn borrow(&self) -> &[T] |
impl Borrow<[u8]> for ByteStr | fn borrow(&self) -> &[u8] |
impl Borrow<[u8]> for ByteString | fn borrow(&self) -> &[u8] |
Трейт BorrowMut
| Тип | Реализация |
|---|---|
impl<T, const N: usize> BorrowMut<[T]> for [T; N] | fn borrow_mut(&mut self) -> &mut [T] |
impl<T, A> BorrowMut<[T]> for Vec<T, A> where A: Allocator | fn borrow_mut(&mut self) -> &mut [T] |
impl BorrowMut<[u8]> for ByteStr | fn borrow_mut(&mut self) -> &mut [u8] |
impl BorrowMut<[u8]> for ByteString | fn borrow_mut(&mut self) -> &mut [u8] |
Трейт BufRead
| Тип | Реализация |
|---|---|
impl BufRead for &[u8] | fn fill_buf(&mut self) -> Result<&[u8]> |
Трейт Clone
| Тип | Реализация |
|---|---|
impl<T, A> Clone for Box<[T], A> where T: Clone, A: Allocator + Clone | fn clone(&self) -> Box<[T], A> |
Трейт Debug
| Тип | Реализация |
|---|---|
impl<T> Debug for [T] where T: Debug | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> |
Трейт Default
| Тип | Реализация |
|---|---|
impl<T> Default for &[T] | fn default() -> &[T] |
impl<T> Default for &mut [T] | fn default() -> &mut [T] |
impl<T> Default for Box<[T]> | fn default() -> Box<[T]> |
Трейт From
| Тип | Реализация |
|---|---|
impl<T> From<&[T]> for Arc<[T]> where T: Clone | fn from(v: &[T]) -> Arc<[T]> |
impl<T> From<&[T]> for Box<[T]> where T: Clone | fn from(slice: &[T]) -> Box<[T]> |
impl<'a, T> From<&'a [T]> for Cow<'a, [T]> where T: Clone | fn from(s: &'a [T]) -> Cow<'a, [T]> |
impl<T> From<&[T]> for Rc<[T]> where T: Clone | fn from(v: &[T]) -> Rc<[T]> |
impl<T> From<&[T]> for Vec<T> where T: Clone | fn from(s: &[T]) -> Vec<T> |
impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> | fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> |
impl<T> From<&mut [T]> for Arc<[T]> where T: Clone | fn from(v: &mut [T]) -> Arc<[T]> |
impl<T> From<&mut [T]> for Box<[T]> where T: Clone | fn from(slice: &mut [T]) -> Box<[T]> |
impl<T> From<&mut [T]> for Rc<[T]> where T: Clone | fn from(v: &mut [T]) -> Rc<[T]> |
impl<T> From<&mut [T]> for Vec<T> where T: Clone | fn from(s: &mut [T]) -> Vec<T> |
impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> | fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> |
impl<T, const N: usize> From<[T; N]> for Box<[T]> | fn from(array: [T; N]) -> Box<[T]> |
impl From<Box<ByteStr>> for Box<[u8]> | fn from(s: Box<ByteStr>) -> Box<[u8]> |
impl<A> From<Box<str, A>> for Box<[u8], A> where A: Allocator | fn from(s: Box<str, A>) -> Box<[u8], A> |
impl<T> From<Cow<'_, [T]>> for Box<[T]> where T: Clone | fn from(cow: Cow<'_, [T]>) -> Box<[T]> |
impl<T, A> From<Vec<T, A>> for Box<[T], A> where A: Allocator | fn from(v: Vec<T, A>) -> Box<[T], A> |
Трейт FromIterator
| Тип | Реализация |
|---|---|
impl<'a> FromIterator<&'a [u8]> for ByteString | fn from_iter<T>(iter: T) -> ByteString where T: IntoIterator<Item = &'a [u8]> |
impl<I> FromIterator<I> for Box<[I]> | fn from_iter<T>(iter: T) -> Box<[I]> where T: IntoIterator<Item = I> |
Трейт Hash
| Тип | Реализация |
|---|---|
impl<T> Hash for [T] where T: Hash | fn hash<H>(&self, state: &mut H) where H: Hasher |
Трейты Index и IndexMut
| Тип | Реализация |
|---|---|
impl<T, I> Index<I> for [T] where I: SliceIndex<[T]> | fn index(&self, index: I) -> &<I as SliceIndex<[T]>>::Output |
impl<T, I> IndexMut<I> for [T] where I: SliceIndex<[T]> | fn index_mut(&mut self, index: I) -> &mut <I as SliceIndex<[T]>>::Output |
Трейт IntoIterator
| Тип | Реализация |
|---|---|
impl<'a, T> IntoIterator for &'a [T] | type Item = &'a T; type IntoIter = Iter<'a, T> |
impl<'a, I, A> IntoIterator for &'a Box<[I], A> where A: Allocator | type Item = &'a I; type IntoIter = Iter<'a, I> |
impl<'a, T> IntoIterator for &'a mut [T] | type Item = &'a mut T; type IntoIter = IterMut<'a, T> |
impl<'a, I, A> IntoIterator for &'a mut Box<[I], A> where A: Allocator | type Item = &'a mut I; type IntoIter = IterMut<'a, I> |
impl<I, A> IntoIterator for Box<[I], A> where A: Allocator | type Item = I; type IntoIter = IntoIter<I, A> |
Трейт Ord
| Тип | Реализация |
|---|---|
impl<T> Ord for [T] where T: Ord | fn cmp(&self, other: &[T]) -> Ordering |
Трейт PartialEq
| Тип | Реализация |
|---|---|
impl<T, U, const N: usize> PartialEq<&[U]> for [T; N] where T: PartialEq<U> | fn eq(&self, other: &&[U]) -> bool |
impl<T, U> PartialEq<&[U]> for Cow<'_, [T]> where T: PartialEq<U> + Clone | fn eq(&self, other: &&[U]) -> bool |
impl<T, U, A> PartialEq<&[U]> for Vec<T, A> where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &&[U]) -> bool |
impl<T, U, A> PartialEq<&[U]> for VecDeque<T, A> where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &&[U]) -> bool |
impl<'a> PartialEq<&[u8]> for ByteStr | fn eq(&self, other: &&[u8]) -> bool |
impl<'a> PartialEq<&[u8]> for ByteString | fn eq(&self, other: &&[u8]) -> bool |
impl<T, U, const N: usize> PartialEq<&mut [U]> for [T; N] where T: PartialEq<U> | fn eq(&self, other: &&mut [U]) -> bool |
impl<T, U> PartialEq<&mut [U]> for Cow<'_, [T]> where T: PartialEq<U> + Clone | fn eq(&self, other: &&mut [U]) -> bool |
impl<T, U, A> PartialEq<&mut [U]> for Vec<T, A> where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &&mut [U]) -> bool |
impl<T, U, A> PartialEq<&mut [U]> for VecDeque<T, A> where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &&mut [U]) -> bool |
impl<T, U> PartialEq<[U]> for [T] where T: PartialEq<U> | fn eq(&self, other: &[U]) -> bool |
impl<T, U, const N: usize> PartialEq<[U]> for [T; N] where T: PartialEq<U> | fn eq(&self, other: &[U]) -> bool |
impl<T, U, A> PartialEq<[U]> for Vec<T, A> where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &[U]) -> bool |
impl<T, U, const N: usize> PartialEq<[U; N]> for &[T] where T: PartialEq<U> | fn eq(&self, other: &[U; N]) -> bool |
impl<T, U, const N: usize> PartialEq<[U; N]> for &mut [T] where T: PartialEq<U> | fn eq(&self, other: &[U; N]) -> bool |
impl<T, U, const N: usize> PartialEq<[U; N]> for [T] where T: PartialEq<U> | fn eq(&self, other: &[U; N]) -> bool |
impl<'a> PartialEq<[u8]> for ByteStr | fn eq(&self, other: &[u8]) -> bool |
impl<'a> PartialEq<[u8]> for ByteString | fn eq(&self, other: &[u8]) -> bool |
impl<'a> PartialEq<ByteStr> for &[u8] | fn eq(&self, other: &ByteStr) -> bool |
impl<'a> PartialEq<ByteStr> for [u8] | fn eq(&self, other: &ByteStr) -> bool |
impl<'a> PartialEq<ByteString> for &[u8] | fn eq(&self, other: &ByteString) -> bool |
impl<'a> PartialEq<ByteString> for [u8] | fn eq(&self, other: &ByteString) -> bool |
impl<T, U, A> PartialEq<Vec<U, A>> for &[T] where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &Vec<U, A>) -> bool |
impl<T, U, A> PartialEq<Vec<U, A>> for &mut [T] where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &Vec<U, A>) -> bool |
impl<T, U, A> PartialEq<Vec<U, A>> for [T] where A: Allocator, T: PartialEq<U> | fn eq(&self, other: &Vec<U, A>) -> bool |
Трейт PartialOrd
| Тип | Реализация |
|---|---|
impl<T> PartialOrd for [T] where T: PartialOrd | fn partial_cmp(&self, other: &[T]) -> Option<Ordering> |
Трейт Pattern
| Тип | Реализация |
|---|---|
impl<'b> Pattern for &'b [char] | type Searcher<'a> = CharSliceSearcher<'a, 'b> |
Трейт Read
| Тип | Реализация |
|---|---|
impl Read for &[u8] | fn read(&mut self, buf: &mut [u8]) -> Result<usize> |
Трейт SliceIndex
| Тип | Реализация |
|---|---|
impl<T> SliceIndex<[T]> for (Bound<usize>, Bound<usize>) | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<Range<usize>> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<RangeFrom<usize>> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<RangeFull> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<RangeInclusive<usize>> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<RangeTo<usize>> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<RangeToInclusive<usize>> | type Output = [T] |
impl<T> SliceIndex<[T]> for Clamp<usize> | type Output = T |
impl<T> SliceIndex<[T]> for Last | type Output = T |
impl<T> SliceIndex<[T]> for Range<usize> | type Output = [T] |
impl<T> SliceIndex<[T]> for RangeFrom<usize> | type Output = [T] |
impl<T> SliceIndex<[T]> for RangeFull | type Output = [T] |
impl<T> SliceIndex<[T]> for RangeInclusive<usize> | type Output = [T] |
impl<T> SliceIndex<[T]> for RangeTo<usize> | type Output = [T] |
impl<T> SliceIndex<[T]> for RangeToInclusive<usize> | type Output = [T] |
impl<T> SliceIndex<[T]> for usize | type Output = T |
Трейт ToOwned
| Тип | Реализация |
|---|---|
impl<T> ToOwned for [T] where T: Clone | type Owned = Vec<T> |
Трейт TryFrom
| Тип | Реализация |
|---|---|
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] | type Error = TryFromSliceError |
impl<T, const N: usize> TryFrom<&[T]> for [T; N] where T: Copy | type Error = TryFromSliceError |
impl<T, const N: usize> TryFrom<&[T]> for Simd<T, N> where LaneCount<N>: SupportedLaneCount, T: SimdElement | type Error = TryFromSliceError |
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] | type Error = TryFromSliceError |
impl<T, const N: usize> TryFrom<&mut [T]> for [T; N] where T: Copy | type Error = TryFromSliceError |
impl<T, const N: usize> TryFrom<&mut [T]> for Simd<T, N> where LaneCount<N>: SupportedLaneCount, T: SimdElement | type Error = TryFromSliceError |
Трейт Write
| Тип | Реализация |
|---|---|
impl Write for &mut [u8] | fn write(&mut self, data: &[u8]) -> Result<usize> |
Автоматические реализации трейтов
| Тип | Трейты |
|---|---|
impl<T> Freeze for [T] where T: Freeze | Freeze |
impl<T> RefUnwindSafe for [T] where T: RefUnwindSafe | RefUnwindSafe |
impl<T> Send for [T] where T: Send | Send |
impl<T> !Sized for [T] | !Sized |
impl<T> Sync for [T] where T: Sync | Sync |
impl<T> Unpin for [T] where T: Unpin | Unpin |
impl<T> UnwindSafe for [T] where T: UnwindSafe | UnwindSafe |
Реализации по умолчанию
| Тип | Трейт |
|---|---|
impl<T> Any for T where T: 'static + ?Sized | Any |
impl<T> Borrow<T> for T where T: ?Sized | Borrow |
impl<T> BorrowMut<T> for T where T: ?Sized | BorrowMut |
Примечание: 🔬 обозначает экспериментальные API, доступные только в ночных сборках Rust.
Примитивный тип str
Строковые срезы
Смотрите также модуль std::str.
Тип str, также называемый "строковым срезом", является наиболее примитивным строковым типом. Обычно встречается в заимствованной форме &str. Также это тип строковых литералов &'static str.
Базовое использование
Строковые литералы являются строковыми срезами:
#![allow(unused)] fn main() { let hello_world = "Hello, World!"; }
Здесь мы объявили строковый срез, инициализированный строковым литералом. Строковые литералы имеют статическое время жизни ('static), что означает, что строка hello_world гарантированно будет корректной на протяжении всей программы. Мы также можем явно указать время жизни hello_world:
#![allow(unused)] fn main() { let hello_world: &'static str = "Hello, world!"; }
Представление
&str состоит из двух компонентов: указателя на байты и длины. Вы можете посмотреть их с помощью методов as_ptr и len:
#![allow(unused)] fn main() { use std::slice; use std::str; let story = "Once upon a time..."; let ptr = story.as_ptr(); let len = story.len(); // story имеет девятнадцать байтов assert_eq!(19, len); // Мы можем воссоздать str из ptr и len. Это небезопасно, потому что // мы ответственны за то, чтобы оба компонента были корректны: let s = unsafe { // Сначала строим &[u8]... let slice = slice::from_raw_parts(ptr, len); // ... и затем преобразуем этот срез в строковый срез str::from_utf8(slice) }; assert_eq!(s, Ok(story)); }
Примечание: Этот пример показывает внутреннее устройство &str. unsafe не должен использоваться для получения строкового среза в обычных обстоятельствах. Вместо этого используйте as_str.
Инвариант
Библиотеки Rust могут предполагать, что строковые срезы всегда являются корректным UTF-8.
Создание не-UTF-8 строкового среза не является немедленным неопределённым поведением, но любая функция, вызванная на строковом срезе, может предполагать, что он является корректным UTF-8, что означает, что не-UTF-8 строковый срез может привести к неопределённому поведению в дальнейшем.
Реализации
impl str
Методы
pub const fn len(&self) -> usize
Возвращает длину self.
Эта длина измеряется в байтах, не в символах или графемах. Другими словами, это может не соответствовать тому, что человек считает длиной строки.
Примеры:
#![allow(unused)] fn main() { let len = "foo".len(); assert_eq!(3, len); assert_eq!("ƒoo".len(), 4); // модная f! assert_eq!("ƒoo".chars().count(), 3); }
pub const fn is_empty(&self) -> bool
Возвращает true, если self имеет нулевую длину в байтах.
Примеры:
#![allow(unused)] fn main() { let s = ""; assert!(s.is_empty()); let s = "not empty"; assert!(!s.is_empty()); }
pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
Преобразует срез байтов в строковый срез.
Строковый срез (&str) состоит из байтов (u8), и срез байтов (&[u8]) также состоит из байтов, поэтому эта функция выполняет преобразование между ними. Однако не все срезы байтов являются корректными строковыми срезами: &str требует, чтобы данные были корректным UTF-8. from_utf8() проверяет, являются ли байты корректным UTF-8, и затем выполняет преобразование.
Если вы уверены, что срез байтов является корректным UTF-8, и не хотите тратить ресурсы на проверку валидности, существует небезопасная версия этой функции - from_utf8_unchecked, которая имеет такое же поведение, но пропускает проверку.
Если вам нужна String вместо &str, рассмотрите String::from_utf8.
Поскольку вы можете разместить [u8; N] в стеке и взять из него &[u8], эта функция является одним из способов получить строку, размещённую в стеке.
Ошибки:
Возвращает Err, если срез не является UTF-8, с описанием причины.
Примеры:
#![allow(unused)] fn main() { // несколько байтов в векторе let sparkle_heart = vec![240, 159, 146, 150]; // Мы можем использовать оператор ? (try) для проверки let sparkle_heart = str::from_utf8(&sparkle_heart)?; assert_eq!("💖", sparkle_heart); }
pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error>
Преобразует изменяемый срез байтов в изменяемый строковый срез.
Примеры:
#![allow(unused)] fn main() { // "Hello, Rust!" в виде изменяемого вектора let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33]; let outstr = str::from_utf8_mut(&mut hellorust).unwrap(); assert_eq!("Hello, Rust!", outstr); }
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str
Преобразует срез байтов в строковый срез без проверки того, что строка содержит корректный UTF-8.
Безопасность: Переданные байты должны быть корректным UTF-8.
Примеры:
#![allow(unused)] fn main() { let sparkle_heart = vec![240, 159, 146, 150]; let sparkle_heart = unsafe { str::from_utf8_unchecked(&sparkle_heart) }; assert_eq!("💖", sparkle_heart); }
pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str
Преобразует срез байтов в строковый срез без проверки того, что строка содержит корректный UTF-8; изменяемая версия.
Примеры:
#![allow(unused)] fn main() { let mut heart = vec![240, 159, 146, 150]; let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) }; assert_eq!("💖", heart); }
pub const fn is_char_boundary(&self, index: usize) -> bool
Проверяет, является ли index-ный байт первым байтом в последовательности UTF-8 или концом строки.
Начало и конец строки (когда index == self.len()) считаются границами.
Возвращает false, если index больше self.len().
Примеры:
#![allow(unused)] fn main() { let s = "Löwe 老虎 Léopard"; assert!(s.is_char_boundary(0)); assert!(s.is_char_boundary(6)); assert!(s.is_char_boundary(s.len())); assert!(!s.is_char_boundary(2)); // второй байт `ö` assert!(!s.is_char_boundary(8)); // третий байт `老` }
pub const fn floor_char_boundary(&self, index: usize) -> usize
Находит ближайший x, не превышающий index, где is_char_boundary(x) истинно.
Примеры:
#![allow(unused)] fn main() { let s = "❤️🧡💛💚💙💜"; assert_eq!(s.len(), 26); assert!(!s.is_char_boundary(13)); let closest = s.floor_char_boundary(13); assert_eq!(closest, 10); assert_eq!(&s[..closest], "❤️🧡"); }
pub const fn ceil_char_boundary(&self, index: usize) -> usize
Находит ближайший x, не меньший index, где is_char_boundary(x) истинно.
Примеры:
#![allow(unused)] fn main() { let s = "❤️🧡💛💚💙💜"; let closest = s.ceil_char_boundary(13); assert_eq!(closest, 14); assert_eq!(&s[..closest], "❤️🧡💛"); }
pub const fn as_bytes(&self) -> &[u8]
Преобразует строковый срез в срез байтов.
Примеры:
#![allow(unused)] fn main() { let bytes = "bors".as_bytes(); assert_eq!(b"bors", bytes); }
pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8]
Преобразует изменяемый строковый срез в изменяемый срез байтов.
Безопасность: Вызывающий должен гарантировать, что содержимое среза остаётся корректным UTF-8.
Примеры:
#![allow(unused)] fn main() { let mut s = String::from("🗻∈🌏"); unsafe { let bytes = s.as_bytes_mut(); bytes[0] = 0xF0; bytes[1] = 0x9F; bytes[2] = 0x8D; bytes[3] = 0x94; } assert_eq!("🍔∈🌏", s); }
pub const fn as_ptr(&self) -> *const u8
Преобразует строковый срез в необработанный указатель.
Примеры:
#![allow(unused)] fn main() { let s = "Hello"; let ptr = s.as_ptr(); }
pub const fn as_mut_ptr(&mut self) -> *mut u8
Преобразует изменяемый строковый срез в необработанный указатель.
pub fn get<I>(&self, i: I) -> Option<&<I as SliceIndex<str>>::Output>
Возвращает под-срез str.
Это непанующий альтернатива индексации str. Возвращает None, когда эквивалентная операция индексации вызвала бы панику.
Примеры:
#![allow(unused)] fn main() { let v = String::from("🗻∈🌏"); assert_eq!(Some("🗻"), v.get(0..4)); assert!(v.get(1..).is_none()); // не на границе UTF-8 }
pub fn get_mut<I>(&mut self, i: I) -> Option<&mut <I as SliceIndex<str>>::Output>
Возвращает изменяемый под-срез str.
pub unsafe fn get_unchecked<I>(&self, i: I) -> &<I as SliceIndex<str>>::Output
Возвращает непроверенный под-срез str.
pub unsafe fn get_unchecked_mut<I>(&mut self, i: I) -> &mut <I as SliceIndex<str>>::Output
Возвращает изменяемый непроверенный под-срез str.
pub const fn split_at(&self, mid: usize) -> (&str, &str)
Делит один строковый срез на два по индексу.
Паника:
Паникует, если mid не находится на границе кодовой точки UTF-8.
Примеры:
#![allow(unused)] fn main() { let s = "Per Martin-Löf"; let (first, last) = s.split_at(3); assert_eq!("Per", first); assert_eq!(" Martin-Löf", last); }
pub const fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
Делит один изменяемый строковый срез на два по индексу.
pub const fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)>
Делит один строковый срез на два по индексу. Возвращает None, если индекс некорректен.
pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)>
Делит один изменяемый строковый срез на два по индексу. Возвращает None, если индекс некорректен.
pub fn chars(&self) -> Chars<'_>
Возвращает итератор по символам (char) строкового среза.
Примеры:
#![allow(unused)] fn main() { let word = "goodbye"; let mut chars = word.chars(); assert_eq!(Some('g'), chars.next()); }
pub fn char_indices(&self) -> CharIndices<'_>
Возвращает итератор по символам строкового среза и их позициям.
pub fn bytes(&self) -> Bytes<'_>
Возвращает итератор по байтам строкового среза.
pub fn split_whitespace(&self) -> SplitWhitespace<'_>
Разделяет строковый срез по пробельным символам Unicode.
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_>
Разделяет строковый срез по ASCII пробельным символам.
pub fn lines(&self) -> Lines<'_>
Возвращает итератор по строкам текста.
pub fn encode_utf16(&self) -> EncodeUtf16<'_>
Возвращает итератор u16 над строкой, закодированной как UTF-16.
pub fn contains<P>(&self, pat: P) -> bool
Возвращает true, если данный паттерн соответствует под-срезу этой строки.
pub fn starts_with<P>(&self, pat: P) -> bool
Возвращает true, если данный паттерн соответствует префиксу этой строки.
pub fn ends_with<P>(&self, pat: P) -> bool
Возвращает true, если данный паттерн соответствует суффиксу этой строки.
pub fn find<P>(&self, pat: P) -> Option<usize>
Возвращает байтовый индекс первого символа, соответствующего паттерну.
pub fn rfind<P>(&self, pat: P) -> Option<usize>
Возвращает байтовый индекс первого символа последнего совпадения паттерна.
pub fn split<P>(&self, pat: P) -> Split<'_, P>
Возвращает итератор по подстрокам, разделённым паттерном.
pub fn split_inclusive<P>(&self, pat: P) -> SplitInclusive<'_, P>
Возвращает итератор по подстрокам, включая разделитель в конец подстроки.
pub fn rsplit<P>(&self, pat: P) -> RSplit<'_, P>
Возвращает итератор по подстрокам в обратном порядке.
pub fn split_terminator<P>(&self, pat: P) -> SplitTerminator<'_, P>
Возвращает итератор по подстрокам, пропуская пустую завершающую подстроку.
pub fn rsplit_terminator<P>(&self, pat: P) -> RSplitTerminator<'_, P>
Возвращает итератор по подстрокам в обратном порядке, пропуская пустую завершающую подстроку.
pub fn splitn<P>(&self, n: usize, pat: P) -> SplitN<'_, P>
Возвращает итератор по подстрокам, ограниченный n элементами.
pub fn rsplitn<P>(&self, n: usize, pat: P) -> RSplitN<'_, P>
Возвращает итератор по подстрокам в обратном порядке, ограниченный n элементами.
pub fn split_once<P>(&self, delimiter: P) -> Option<(&str, &str)>
Разделяет строку по первому вхождению разделителя.
pub fn rsplit_once<P>(&self, delimiter: P) -> Option<(&str, &str)>
Разделяет строку по последнему вхождению разделителя.
pub fn matches<P>(&self, pat: P) -> Matches<'_, P>
Возвращает итератор по непересекающимся совпадениям паттерна.
pub fn rmatches<P>(&self, pat: P) -> RMatches<'_, P>
Возвращает итератор по непересекающимся совпадениям паттерна в обратном порядке.
pub fn match_indices<P>(&self, pat: P) -> MatchIndices<'_, P>
Возвращает итератор по совпадениям паттерна и их индексам.
pub fn rmatch_indices<P>(&self, pat: P) -> RMatchIndices<'_, P>
Возвращает итератор по совпадениям паттерна и их индексам в обратном порядке.
pub fn trim(&self) -> &str
Возвращает строковый срез с удалёнными начальными и конечными пробельными символами Unicode.
pub fn trim_start(&self) -> &str
Возвращает строковый срез с удалёнными начальными пробельными символами.
pub fn trim_end(&self) -> &str
Возвращает строковый срез с удалёнными конечными пробельными символами.
pub fn trim_matches<P>(&self, pat: P) -> &str
Возвращает строковый срез с удалёнными всеми префиксами и суффиксами, соответствующими паттерну.
pub fn trim_start_matches<P>(&self, pat: P) -> &str
Возвращает строковый срез с удалёнными всеми префиксами, соответствующими паттерну.
pub fn strip_prefix<P>(&self, prefix: P) -> Option<&str>
Возвращает строковый срез с удалённым префиксом (точно один раз).
pub fn strip_suffix<P>(&self, suffix: P) -> Option<&str>
Возвращает строковый срез с удалённым суффиксом (точно один раз).
pub fn trim_end_matches<P>(&self, pat: P) -> &str
Возвращает строковый срез с удалёнными всеми суффиксами, соответствующими паттерну.
pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err>
Парсит этот строковый срез в другой тип.
pub const fn is_ascii(&self) -> bool
Проверяет, находятся ли все символы в строке в диапазоне ASCII.
pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool
Проверяет, являются ли две строки одинаковыми без учёта регистра ASCII.
pub const fn make_ascii_uppercase(&mut self)
Преобразует строку в верхний регистр ASCII на месте.
pub const fn make_ascii_lowercase(&mut self)
Преобразует строку в нижний регистр ASCII на месте.
pub const fn trim_ascii_start(&self) -> &str
Возвращает строковый срез с удалёнными начальными пробельными символами ASCII.
pub const fn trim_ascii_end(&self) -> &str
Возвращает строковый срез с удалёнными конечными пробельными символами ASCII.
pub const fn trim_ascii(&self) -> &str
Возвращает строковый срез с удалёнными начальными и конечными пробельными символами ASCII.
pub fn escape_debug(&self) -> EscapeDebug<'_>
Возвращает итератор, экранирующий каждый символ с помощью char::escape_debug.
pub fn escape_default(&self) -> EscapeDefault<'_>
Возвращает итератор, экранирующий каждый символ с помощью char::escape_default.
pub fn escape_unicode(&self) -> EscapeUnicode<'_>
Возвращает итератор, экранирующий каждый символ с помощью char::escape_unicode.
impl str (Методы для строковых срезов)
pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]>
Преобразует Box<str> в Box<[u8]> без копирования или аллокации.
pub fn replace<P>(&self, from: P, to: &str) -> String
Заменяет все вхождения паттерна другой строкой.
pub fn replacen<P>(&self, pat: P, to: &str, count: usize) -> String
Заменяет первые N вхождений паттерна другой строкой.
pub fn to_lowercase(&self) -> String
Возвращает строку в нижнем регистре Unicode.
pub fn to_uppercase(&self) -> String
Возвращает строку в верхнем регистре Unicode.
pub fn repeat(&self, n: usize) -> String
Создаёт новую String, повторяя строку n раз.
pub fn to_ascii_uppercase(&self) -> String
Возвращает копию строки, где каждый символ преобразован в верхний регистр ASCII.
pub fn to_ascii_lowercase(&self) -> String
Возвращает копию строки, где каждый символ преобразован в нижний регистр ASCII.
Реализации трейтов
impl<'a> Add<&'a str> for Cow<'a, str>
impl Add<&str> for String
impl<'a> AddAssign<&'a str> for Cow<'a, str>
impl AddAssign<&str> for String
impl AsMut<str> for String
impl AsRef<[u8]> for str
impl AsRef<OsStr> for str
impl AsRef<Path> for str
impl Borrow<str> for String
impl BorrowMut<str> for String
impl Clone for Box<str>
impl Debug for str
impl Default for &str
impl Display for str
impl<'a> Extend<&'a str> for String
impl From<&str> for String
impl From<&str> for Vec<u8>
impl<'a> FromIterator<&'a str> for String
impl Hash for str
impl<I> Index<I> for str
impl<I> IndexMut<I> for str
impl Ord for str
impl PartialEq for str
impl PartialOrd for str
impl<'b> Pattern for &'b str
impl ToOwned for str
impl ToSocketAddrs for str
impl Eq for str
Автоматические реализации трейтов
Freeze for strRefUnwindSafe for strSend for str!Sized for str(не имеет размера во время компиляции)Sync for strUnpin for strUnwindSafe for str
Примитивный тип tuple
Кортеж — конечная разнородная последовательность: (T, U, ..).
Рассмотрим каждое свойство по порядку:
Свойства кортежей
-
Конечность: Кортеж имеет длину. Например, кортеж длины 3:
#![allow(unused)] fn main() { ("hello", 5, 'c'); }Длина также называется "арностью" (arity). Каждый кортеж разной длины — это отдельный, уникальный тип.
-
Разнородность: Каждый элемент кортежа может иметь разный тип. Указанный выше кортеж имеет тип:
#![allow(unused)] fn main() { (&'static str, i32, char) } -
Последовательность: Элементы кортежа доступны по позиции с помощью "индексации кортежа":
#![allow(unused)] fn main() { let tuple = ("hello", 5, 'c'); assert_eq!(tuple.0, "hello"); assert_eq!(tuple.1, 5); assert_eq!(tuple.2, 'c'); }
Последовательная природа кортежа влияет на реализации различных трейтов. Например, в PartialOrd и Ord элементы сравниваются последовательно до первого несовпадающего набора.
Реализации трейтов
В документации используется сокращение (T₁, T₂, …, Tₙ) для представления кортежей различной длины. Когда это используется, любая граница трейта, выраженная на T, применяется к каждому элементу кортежа независимо. Это обозначение для удобства документации, а не валидный синтаксис Rust.
Трейты с ограничением по длине (до 12 элементов)
Из-за временных ограничений в системе типов Rust следующие трейты реализованы только для кортежей длиной до 12 элементов:
| Трейт | Описание |
|---|---|
PartialEq, Eq | Проверка на равенство |
PartialOrd, Ord | Сравнение |
Debug | Отладочный вывод |
Default | Значение по умолчанию |
Hash | Хеширование |
From<[T; N]> | Преобразование из массива |
Трейты для кортежей любой длины
Следующие трейты реализованы для кортежей любой длины. Их реализации автоматически генерируются компилятором:
| Трейт | Описание |
|---|---|
Clone, Copy | Клонирование и копирование |
Send, Sync | Многопоточность |
Unpin | Перемещение |
UnwindSafe, RefUnwindSafe | Безопасность при раскрутке стека |
Таблица реализаций трейтов
Основные трейты
| Трейт | Элементы | Версия | Примечание |
|---|---|---|---|
Debug | T: Debug | 1.0.0 | До 12 элементов |
Default | T: Default | 1.0.0 | До 12 элементов |
Hash | T: Hash | 1.0.0 | До 12 элементов |
Ord | T: Ord | 1.0.0 | До 12 элементов |
PartialEq | T: PartialEq | 1.0.0 | До 12 элементов |
PartialOrd | T: PartialOrd | 1.0.0 | До 12 элементов |
Eq | T: Eq | 1.0.0 | До 12 элементов |
Трейты коллекций
| Трейт | Тип | Версия | Описание |
|---|---|---|---|
Extend<(K, V)> | BTreeMap<K, V, A> | 1.0.0 | Расширение BTreeMap парами |
Extend<(K, V)> | HashMap<K, V, S> | 1.0.0 | Расширение HashMap парами |
Extend<(&K, &V)> | BTreeMap<K, V, A> | 1.2.0 | Расширение ссылками на пары |
Extend<(&K, &V)> | HashMap<K, V, S> | 1.4.0 | Расширение ссылками на пары |
Extend<(T₁, T₂, …, Tₙ)> | (ExtendT₁, ExtendT₂, …) | 1.56.0 | Расширение кортежей коллекций |
FromIterator<(K, V)> | BTreeMap<K, V> | 1.0.0 | Создание из итератора пар |
FromIterator<(K, V)> | HashMap<K, V, S> | 1.0.0 | Создание из итератора пар |
FromIterator<(T₁, T₂, …, Tₙ)> | (ExtendT₁, ExtendT₂, …) | 1.79.0 | Создание кортежей коллекций |
Преобразования From/Into
| Преобразование | Назначение | Версия | Описание |
|---|---|---|---|
[T; N] → (T₁, T₂, …, Tₙ) | Кортеж | 1.71.0 | До 12 элементов |
(T₁, T₂, …, Tₙ) → [T; N] | Массив | 1.71.0 | До 12 элементов |
(I, u16) → SocketAddr | Адрес сокета | 1.17.0 | Из IP-адреса и порта |
Трейты для работы с диапазонами
| Трейт | Тип | Версия | Описание |
|---|---|---|---|
RangeBounds<T> | (Bound<T>, Bound<T>) | 1.28.0 | Границы диапазона |
RangeBounds<T> | (Bound<&T>, Bound<&T>) | 1.28.0 | Границы диапазона по ссылке |
IntoBounds<T> | (Bound<T>, Bound<T>) | nightly | Преобразование в границы |
SliceIndex<[T]> | (Bound<usize>, Bound<usize>) | 1.53.0 | Индексация срезов |
SliceIndex<str> | (Bound<usize>, Bound<usize>) | 1.73.0 | Индексация строк |
Сетевые трейты
| Трейт | Тип | Версия | Описание |
|---|---|---|---|
ToSocketAddrs | (&str, u16) | 1.0.0 | Преобразование в адреса сокетов |
ToSocketAddrs | (IpAddr, u16) | 1.0.0 | Преобразование в адреса сокетов |
ToSocketAddrs | (Ipv4Addr, u16) | 1.0.0 | Преобразование в адреса сокетов |
ToSocketAddrs | (Ipv6Addr, u16) | 1.0.0 | Преобразование в адреса сокетов |
ToSocketAddrs | (String, u16) | 1.46.0 | Преобразование в адреса сокетов |
Примеры
Базовое использование
#![allow(unused)] fn main() { let tuple = ("hello", 5, 'c'); assert_eq!(tuple.0, "hello"); }
Использование как возвращаемого типа
#![allow(unused)] fn main() { fn calculate_point() -> (i32, i32) { (4, 5) } let point = calculate_point(); assert_eq!(point.0, 4); assert_eq!(point.1, 5); // С использованием паттернов let (x, y) = calculate_point(); assert_eq!(x, 4); assert_eq!(y, 5); }
Создание из массива
#![allow(unused)] fn main() { let array: [u32; 3] = [1, 2, 3]; let tuple: (u32, u32, u32) = array.into(); }
Использование Extend с кортежами коллекций
#![allow(unused)] fn main() { let mut tuple = (vec![0], vec![1]); tuple.extend([(2, 3), (4, 5), (6, 7)]); assert_eq!(tuple.0, [0, 2, 4, 6]); assert_eq!(tuple.1, [1, 3, 5, 7]); }
Использование FromIterator
#![allow(unused)] fn main() { let string = "1,2,123,4"; let (numbers, lengths): (Vec<_>, Vec<_>) = string .split(',') .map(|s| s.parse().map(|n: u32| (n, s.len()))) .collect::<Result<_, _>>()?; assert_eq!(numbers, [1, 2, 123, 4]); assert_eq!(lengths, [1, 1, 3, 1]); }
Использование как диапазона
#![allow(unused)] fn main() { let range = (Bound::Included(0), Bound::Excluded(10)); let slice = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let subslice = &slice[range]; assert_eq!(subslice, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); }
Особые реализации
Служебные трейты (для любых длин)
CloneFromCell— для кортежей до 12 элементов (еслиT: CloneFromCell)ConstParamTy_— для кортежей до 12 элементов (еслиT: ConstParamTy_)StructuralPartialEq— для кортежей до 12 элементов
Автоматические реализации (для любых длин)
Freeze,RefUnwindSafe,Send,Sync,Unpin,UnwindSafe— если все элементы реализуют соответствующий трейт
Примечания
- Индексация: Индексы кортежа начинаются с 0:
tuple.0,tuple.1, и т.д. - Сравнение: Кортежи сравниваются лексикографически, последовательно сравнивая элементы.
- Длина: В текущей версии Rust (1.0.0+) многие трейты ограничены кортежами длиной до 12 элементов, но это может измениться в будущем.
- Паттерны: Кортежи отлично работают с деструктуризацией в паттернах.
Примитивный тип unit (единичный тип)
Тип (), также называемый "единичным" (unit).
Тип () имеет ровно одно значение (), и используется, когда нет другого значимого значения, которое может быть возвращено.
Описание
() чаще всего встречается неявно:
- Функции без указания возвращаемого типа (
-> ...) неявно имеют тип возвращаемого значения().
Эти функции эквивалентны:
#![allow(unused)] fn main() { fn long() -> () {} fn short() {} }
Использование точки с запятой ;
Точка с запятой ; может использоваться для отбрасывания результата выражения в конце блока, заставляя выражение (и, следовательно, блок) вычисляться в ().
Примеры
#![allow(unused)] fn main() { fn returns_i64() -> i64 { 1i64 } fn returns_unit() { 1i64; // Точка с запятой отбрасывает результат } let is_i64 = { returns_i64() // Без точки с запятой - возвращает i64 }; let is_unit = { returns_i64(); // С точкой с запятой - возвращает () }; }
Реализации трейтов
Реализация Debug
| Метод | Описание | Версия | Пример |
|---|---|---|---|
fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | Форматирует значение с помощью заданного форматировщика. | 1.0.0 | println!("{:?}", ()); // Выводит: () |
Реализация Default
| Метод | Описание | Константность | Версия |
|---|---|---|---|
default() -> () | Возвращает значение по умолчанию для (). | - | 1.0.0 |
Реализация Extend<()> для ()
| Метод | Описание | Версия | Статус |
|---|---|---|---|
extend<T>(&mut self, iter: T) | Расширяет коллекцию содержимым итератора. | 1.28.0 | Стабильный |
extend_one(&mut self, _item: ()) | Расширяет коллекцию ровно одним элементом. | Nightly | Экспериментальный |
extend_reserve(&mut self, additional: usize) | Резервирует ёмкость в коллекции для заданного количества дополнительных элементов. | Nightly | Экспериментальный |
Реализация FromIterator<()> для ()
| Метод | Описание | Версия | Пример |
|---|---|---|---|
from_iter<I>(iter: I) | Создаёт значение из итератора. Сворачивает все единичные элементы из итератора в один. | 1.23.0 | `let res: Result<()> = data.iter().map( |
Реализация Hash
| Метод | Описание | Версия |
|---|---|---|
hash<H>(&self, _state: &mut H) | Подаёт это значение в заданный Hasher. | 1.0.0 |
hash_slice<H>(data: &[Self], state: &mut H) | Подаёт срез этого типа в заданный Hasher. | 1.3.0 |
Реализация Ord
| Метод | Описание | Константность | Версия |
|---|---|---|---|
cmp(&self, _other: &()) -> Ordering | Сравнивает self с other. | - | 1.0.0 |
max(self, other: Self) -> Self | Сравнивает и возвращает максимум двух значений. | - | 1.21.0 |
min(self, other: Self) -> Self | Сравнивает и возвращает минимум двух значений. | - | 1.21.0 |
clamp(self, min: Self, max: Self) -> Self | Ограничивает значение определённым интервалом. | - | 1.50.0 |
Реализация PartialEq
| Метод | Описание | Константность | Версия |
|---|---|---|---|
eq(&self, _other: &()) -> bool | Проверяет равенство значений self и other. | - | 1.0.0 |
ne(&self, _other: &()) -> bool | Проверяет неравенство значений. | - | 1.0.0 |
Реализация PartialOrd
| Метод | Описание | Константность | Версия |
|---|---|---|---|
partial_cmp(&self, _: &()) -> Option<Ordering> | Возвращает упорядочение между self и other, если оно существует. | - | 1.0.0 |
lt(&self, other: &Rhs) -> bool | Проверяет "меньше" (для self и other). | - | 1.0.0 |
le(&self, other: &Rhs) -> bool | Проверяет "меньше или равно" (для self и other). | - | 1.0.0 |
gt(&self, other: &Rhs) -> bool | Проверяет "больше" (для self и other). | - | 1.0.0 |
ge(&self, other: &Rhs) -> bool | Проверяет "больше или равно" (для self и other). | - | 1.0.0 |
Реализация Termination
| Метод | Описание | Версия |
|---|---|---|
report(self) -> ExitCode | Вызывается для получения представления значения в виде кода завершения. | 1.61.0 |
Примеры использования
1. Функции без возвращаемого значения
#![allow(unused)] fn main() { fn print_hello() { println!("Hello!"); // Неявно возвращает () } fn explicit_return() -> () { println!("Explicit"); // Явно возвращает () } }
2. Отбрасывание результатов
#![allow(unused)] fn main() { let x = { let y = 5 + 3; y * 2 // Возвращает 16 (i32) }; let unit = { let y = 5 + 3; y * 2; // Точка с запятой отбрасывает результат, возвращает () }; }
3. Коллекции и итераторы
#![allow(unused)] fn main() { use std::io::*; let data = vec![1, 2, 3, 4, 5]; // Собираем все результаты записи в единый Result<()> let res: Result<()> = data.iter() .map(|x| writeln!(stdout(), "{x}")) .collect(); assert!(res.is_ok()); }
4. Паттерн-матчинг
#![allow(unused)] fn main() { fn process_result(result: Result<i32, String>) -> () { match result { Ok(value) => println!("Got value: {}", value), Err(error) => println!("Error: {}", error), } } }
Автоматические реализации трейтов
| Трейт | Описание |
|---|---|
Freeze | Тип можно безопасно замораживать. |
RefUnwindSafe | Ссылки на этот тип безопасны при размотке стека. |
Send | Значения этого типа можно безопасно передавать между потоками. |
Sync | Ссылки на этот тип можно безопасно использовать из нескольких потоков одновременно. |
Unpin | Значения этого типа можно безопасно перемещать. |
UnwindSafe | Значения этого типа безопасны при размотке стека. |
Специальные реализации
| Трейт | Описание | Версия |
|---|---|---|
ConstParamTy_ | Тип может использоваться как параметр константного типа. | - |
Eq | Тип реализует отношение эквивалентности. | 1.0.0 |
StructuralPartialEq | Структурное частичное равенство. | - |
Модули стандартной библиотеки Rust
Общее понятие
Модули в стандартной библиотеке Rust — это организационные единицы, которые группируют связанную функциональность, типы, трейты и константы. Они образуют иерархическую структуру, которая помогает организовать код логичным и удобным для использования способом.
Структура модулей
Стандартная библиотека (std) организована в виде дерева модулей, где корневым является псевдомодуль std:
std/
├── collections/ // Коллекции данных
├── io/ // Ввод-вывод
├── fs/ // Файловая система
├── net/ // Сетевое программирование
├── thread/ // Многопоточность
├── sync/ // Синхронизация
├── convert/ // Преобразования типов
├── option/ // Работа с Option
├── result/ // Работа с Result
└── ... и многие другие
Назначение модулей
Организация кода
Каждый модуль содержит логически связанную функциональность:
std::collections— структуры данных (HashMap, Vec, String)std::io— операции ввода-выводаstd::thread— многопоточное программирование
Сокрытие реализации
Модули позволяют скрывать внутренние детали реализации, предоставляя только публичный API:
#![allow(unused)] fn main() { // Внутренние структуры могут быть скрыты mod internal { pub(crate) struct InternalData; pub struct PublicInterface { // публичные поля } } }
Управление областью видимости
Модули контролируют видимость элементов через модификаторы доступа:
pub— публичная видимостьpub(crate)— видимость в пределах крейтаpub(super)— видимость в родительском модуле
Использование модулей
Импорт функциональности
#![allow(unused)] fn main() { use std::collections::HashMap; use std::io::{Read, Write}; use std::fs::File; }
Квалифицированный доступ
#![allow(unused)] fn main() { let map = std::collections::HashMap::new(); let file = std::fs::File::open("file.txt"); }
Основные категории модулей
Базовые типы и операции
primitive— примитивные типыconvert— преобразования типовops— перегрузка операторов
Структуры данных
collections— коллекцииstring— работа со строкамиvec— векторы
Системное программирование
io— ввод-выводfs— файловая системаnet— сетевое программированиеprocess— управление процессами
Многопоточность
thread— потоки выполненияsync— примитивы синхронизации
Утилиты
fmt— форматированиеdefault— значения по умолчаниюclone— клонирование
Практическое использование
Минимальные импорты
#![allow(unused)] fn main() { // Вместо использования всего std use std::collections::HashMap; use std::io::Result; }
Re-export для удобства
Некоторые типы реэкспортируются на верхнем уровне:
#![allow(unused)] fn main() { // Vec доступен напрямую из std use std::vec::Vec; // Так тоже можно use std::Vec; // Но так проще }
Модуль convert
Содержит Трейты для преобразований между типами.
Трейты в этом модуле предоставляют способ преобразования из одного типа в другой. Каждый трейт служит своей цели:
- Реализуйте трейт
AsRefдля дешёвых преобразований ссылка-в-ссылку - Реализуйте трейт
AsMutдля дешёвых преобразований изменяемая-сссылка-в-изменяемую-ссылку - Реализуйте трейт
Fromдля потребляющих преобразований значение-в-значение - Реализуйте трейт
Intoдля потребляющих преобразований значение-в-значение в типы за пределами текущего крейта - Трейты
TryFromиTryIntoведут себя какFromиInto, но должны реализовываться, когда преобразование может завершиться неудачей.
Трейты в этом модуле часто используются как трейт-границы для обобщённых функций, чтобы поддерживать аргументы нескольких типов. Смотрите документацию каждого трейта для примеров.
Как автор библиотеки, вы всегда должны предпочитать реализацию From<T> или TryFrom<T> вместо Into<U> или TryInto<U>, поскольку From и TryFrom предоставляют большую гибкость и предлагают эквивалентные реализации Into или TryInto бесплатно, благодаря обобщённой реализации в стандартной библиотеке. При работе с версиями до Rust 1.41 может быть необходимо реализовывать Into или TryInto напрямую при преобразовании в тип за пределами текущего крейта.
Обобщённые реализации
AsRefиAsMutавтоматически разыменовываются, если внутренний тип является ссылкой (но не для всех типов, которые можно разыменовать вообще)From<U> for TподразумеваетInto<T> for UTryFrom<U> for TподразумеваетTryInto<T> for UFromиIntoрефлексивны, что означает, что все типы могут преобразовываться в самих себя и из самих себя
Смотрите примеры использования в каждом трейте.
Enums
Infallible
Тип ошибки для ошибок, которые никогда не могут произойти.
Traits
AsMut
Используется для дешёвого преобразования изменяемая-ссылка-в-изменяемую-ссылку.
AsRef
Используется для дешёвого преобразования ссылка-в-ссылку.
From
Используется для преобразований значение-в-значение с потреблением входного значения. Является обратным к Into.
Into
Преобразование значение-в-значение, которое потребляет входное значение. Противоположность From.
TryFrom
Простые и безопасные преобразования типов, которые могут завершаться неудачей контролируемым образом в некоторых обстоятельствах. Является обратным к TryInto.
TryInto
Попытка преобразования, которая потребляет self и может быть как дорогой, так и дешёвой.
FloatToInt (Experimental)
Вспомогательный трейт для inherent-методов f32 и f64, таких как to_int_unchecked. Обычно не требуется использовать напрямую.
Функции
identity
Функция тождества.
Трейт AsMut
#![allow(unused)] fn main() { pub trait AsMut<T> where T: ?Sized, { // Обязательный метод fn as_mut(&mut self) -> &mut T; } }
Используется для дешёвого преобразования изменяемая-ссылка-в-изменяемую-ссылку.
Этот трейт похож на AsRef, но используется для преобразований между изменяемыми ссылками. Если вам нужно выполнить дорогое преобразование, лучше реализовать From с типом &mut T или написать пользовательскую функцию.
Примечание: Этот трейт не должен завершаться неудачей. Если преобразование может завершиться неудачей, используйте специальный метод, который возвращает Option<T> или Result<T, E>.
Обобщённые реализации
AsMut автоматически разыменовывается, если внутренний тип является изменяемой ссылкой (например: foo.as_mut() будет работать одинаково, если foo имеет тип &mut Foo или &mut &mut Foo).
Обратите внимание, что по историческим причинам вышесказанное в настоящее время не выполняется вообще для всех типов, которые можно изменяемо разыменовать, например, foo.as_mut() не будет работать так же, как Box::new(foo).as_mut(). Вместо этого многие умные указатели предоставляют реализацию as_mut, которая просто возвращает ссылку на указываемое значение (но не выполняет дешёвое преобразование ссылка-в-ссылку для этого значения). Однако AsMut::as_mut не следует использовать исключительно для изменяемого разыменования; вместо этого можно использовать "Deref coercion":
#![allow(unused)] fn main() { let mut x = Box::new(5i32); // Избегайте этого: // let y: &mut i32 = x.as_mut(); // Лучше просто написать: let y: &mut i32 = &mut x; }
Типы, которые реализуют DerefMut, должны рассматривать возможность добавления реализации AsMut<T> следующим образом:
#![allow(unused)] fn main() { impl<T> AsMut<T> for SomeType where <SomeType as Deref>::Target: AsMut<T>, { fn as_mut(&mut self) -> &mut T { self.deref_mut().as_mut() } } }
Рефлексивность
В идеале AsMut был бы рефлексивным, т.е. существовала бы реализация impl<T: ?Sized> AsMut<T> for T с as_mut, просто возвращающим свой аргумент без изменений. Такая обобщённая реализация в настоящее время не предоставляется из-за технических ограничений системы типов Rust (она перекрывалась бы с другой существующей обобщённой реализацией для &mut T where T: AsMut<U>, которая позволяет AsMut автоматически разыменовываться, см. "Обобщённые реализации" выше).
Тривиальная реализация AsMut<T> for T должна быть добавлена явно для конкретного типа T, где это необходимо или желательно. Обратите внимание, однако, что не все типы из std содержат такую реализацию, и они не могут быть добавлены внешним кодом из-за правил сиротства.
Примеры
Используя AsMut как трейт-границу для обобщённой функции, мы можем принимать все изменяемые ссылки, которые могут быть преобразованы в тип &mut T. В отличие от разыменования, которое имеет единственный целевой тип, для типа может быть несколько реализаций AsMut. В частности, Vec<T> реализует как AsMut<Vec<T>>, так и AsMut<[T]>.
В следующем примере функции caesar и null_terminate предоставляют обобщённый интерфейс, который работает с любым типом, который может быть преобразован дешёвым преобразованием изменяемая-ссылка-в-изменяемую-ссылку в байтовый срез ([u8]) или байтовый вектор (Vec<u8>) соответственно.
struct Document { info: String, content: Vec<u8>, } impl<T: ?Sized> AsMut<T> for Document where Vec<u8>: AsMut<T>, { fn as_mut(&mut self) -> &mut T { self.content.as_mut() } } fn caesar<T: AsMut<[u8]>>(data: &mut T, key: u8) { for byte in data.as_mut() { *byte = byte.wrapping_add(key); } } fn null_terminate<T: AsMut<Vec<u8>>>(data: &mut T) { // Использование необобщённой внутренней функции, которая содержит большую часть // функциональности, помогает минимизировать накладные расходы на мономорфизацию. fn doit(data: &mut Vec<u8>) { let len = data.len(); if len == 0 || data[len-1] != 0 { data.push(0); } } doit(data.as_mut()); } fn main() { let mut v: Vec<u8> = vec![1, 2, 3]; caesar(&mut v, 5); assert_eq!(v, [6, 7, 8]); null_terminate(&mut v); assert_eq!(v, [6, 7, 8, 0]); let mut doc = Document { info: String::from("Example"), content: vec![17, 19, 8], }; caesar(&mut doc, 1); assert_eq!(doc.content, [18, 20, 9]); null_terminate(&mut doc); assert_eq!(doc.content, [18, 20, 9, 0]); }
Обратите внимание, однако, что API не обязательно должны быть обобщёнными. Во многих случаях принятие &mut [u8] или &mut Vec<u8>, например, является лучшим выбором (тогда вызывающие стороны должны передавать правильный тип).
Обязательные методы
1.0.0 · Source
#![allow(unused)] fn main() { fn as_mut(&mut self) -> &mut T }
Преобразует этот тип в изменяемую ссылку на (обычно выводимый) входной тип.
Реализаторы
Сводная таблица реализаций трейта AsMut<T>
| Исходный тип | Целевой тип T | Описание преобразования |
|---|---|---|
&mut [T] | [T] | Изменяемая ссылка на срез → изменяемый срез |
&mut str | str | Изменяемая ссылка на строку → изменяемый строковый срез |
&mut String | str | Изменяемая ссылка на String → изменяемый строковый срез |
String | str | String → изменяемый строковый срез |
Vec<T> | [T] | Vec → изменяемый срез |
&mut Vec<T> | [T] | Изменяемая ссылка на Vec → изменяемый срез |
[T; N] | [T] | Массив → изменяемый срез |
&mut [T; N] | [T] | Изменяемая ссылка на массив → изменяемый срез |
Box<T> | T | Box → изменяемая ссылка на содержимое |
&mut Box<T> | T | Изменяемая ссылка на Box → изменяемая ссылка на содержимое |
Rc<T> | T | Rc → изменяемая ссылка на содержимое (только если нет других ссылок) |
&mut Rc<T> | T | Изменяемая ссылка на Rc → изменяемая ссылка на содержимое |
Arc<T> | T | Arc → изменяемая ссылка на содержимое (только если нет других ссылок) |
&mut Arc<T> | T | Изменяемая ссылка на Arc → изменяемая ссылка на содержимое |
Cell<T> | T | Cell → изменяемая ссылка на содержимое |
RefCell<T> | T | RefCell → изменяемая ссылка на содержимое |
Mutex<T> | T | Mutex → изменяемая ссылка на содержимое |
RwLock<T> | T | RwLock → изменяемая ссылка на содержимое |
Cow<'_, B> | B | Clone-on-write → изменяемая ссылка на содержимое |
VecDeque<T> | [T] | VecDeque → изменяемый срез |
&mut VecDeque<T> | [T] | Изменяемая ссылка на VecDeque → изменяемый срез |
PathBuf | str | PathBuf → изменяемый строковый срез |
&mut PathBuf | str | Изменяемая ссылка на PathBuf → изменяемый строковый срез |
OsString | str | OsString → изменяемый строковый срез (если валидный UTF-8) |
&mut OsString | str | Изменяемая ссылка на OsString → изменяемый строковый срез |
Трейт AsRef
#![allow(unused)] fn main() { pub trait AsRef<T> where T: ?Sized, { // Обязательный метод fn as_ref(&self) -> &T; } }
Используется для эффективного преобразования ссылка-в-ссылку.
Этот трейт похож на AsMut, который используется для преобразований между изменяемыми ссылками. Если вам нужно выполнить дорогое преобразование, лучше реализовать From с типом &T или написать пользовательскую функцию.
Связь с Borrow
AsRef имеет ту же сигнатуру, что и Borrow, но Borrow отличается в нескольких аспектах:
- В отличие от
AsRef,Borrowимеет обобщённую реализацию для любогоTи может использоваться для принятия как ссылки, так и значения. (Смотрите также примечание о рефлексивностиAsRefниже.) Borrowтакже требует, чтобыHash,EqиOrdдля заимствованного значения были эквивалентны таковым для владеемого значения. По этой причине, если вы хотите заимствовать только одно поле структуры, вы можете реализоватьAsRef, но неBorrow.
Примечание: Этот трейт не должен завершаться неудачей. Если преобразование может завершиться неудачей, используйте специальный метод, который возвращает Option<T> или Result<T, E>.
Обобщённые реализации
AsRef автоматически разыменовывается, если внутренний тип является ссылкой или изменяемой ссылкой (например: foo.as_ref() будет работать одинаково, если foo имеет тип &mut Foo или &&mut Foo).
Обратите внимание, что по историческим причинам вышесказанное в настоящее время не выполняется вообще для всех типов, которые можно разыменовать, например, foo.as_ref() не будет работать так же, как Box::new(foo).as_ref(). Вместо этого многие умные указатели предоставляют реализацию as_ref, которая просто возвращает ссылку на указываемое значение (но не выполняет дешёвое преобразование ссылка-в-ссылку для этого значения). Однако AsRef::as_ref не следует использовать исключительно для разыменования; вместо этого можно использовать "Deref coercion":
#![allow(unused)] fn main() { let x = Box::new(5i32); // Избегайте этого: // let y: &i32 = x.as_ref(); // Лучше просто написать: let y: &i32 = &x; }
Типы, которые реализуют Deref, должны рассматривать возможность реализации AsRef<T> следующим образом:
#![allow(unused)] fn main() { impl<T> AsRef<T> for SomeType where T: ?Sized, <SomeType as Deref>::Target: AsRef<T>, { fn as_ref(&self) -> &T { self.deref().as_ref() } } }
Рефлексивность
В идеале AsRef был бы рефлексивным, т.е. существовала бы реализация impl<T: ?Sized> AsRef<T> for T с as_ref, просто возвращающим свой аргумент без изменений. Такая обобщённая реализация в настоящее время не предоставляется из-за технических ограничений системы типов Rust (она перекрывалась бы с другой существующей обобщённой реализацией для &T where T: AsRef<U>, которая позволяет AsRef автоматически разыменовываться, см. "Обобщённые реализации" выше).
Тривиальная реализация AsRef<T> for T должна быть добавлена явно для конкретного типа T, где это необходимо или желательно. Обратите внимание, однако, что не все типы из std содержат такую реализацию, и они не могут быть добавлены внешним кодом из-за правил сиротства.
Примеры
Используя трейт-границы, мы можем принимать аргументы разных типов, если они могут быть преобразованы в указанный тип T.
Например: Создав обобщённую функцию, которая принимает AsRef<str>, мы выражаем, что хотим принимать все ссылки, которые могут быть преобразованы в &str, как аргумент. Поскольку и String, и &str реализуют AsRef<str>, мы можем принимать оба как входные аргументы.
#![allow(unused)] fn main() { fn is_hello<T: AsRef<str>>(s: T) { assert_eq!("hello", s.as_ref()); } let s = "hello"; is_hello(s); let s = "hello".to_string(); is_hello(s); }
Обязательные методы
1.0.0 · Source
#![allow(unused)] fn main() { fn as_ref(&self) -> &T }
Преобразует этот тип в разделяемую ссылку на (обычно выводимый) входной тип.
Сводная таблица реализаций трейта AsRef<T>
| Исходный тип | Целевой тип T | Описание преобразования |
|---|---|---|
&[T] | [T] | Ссылка на срез → срез |
&mut [T] | [T] | Изменяемая ссылка на срез → срез |
&str | str | Ссылка на строку → строковый срез |
&mut str | str | Изменяемая ссылка на строку → строковый срез |
&String | str | Ссылка на String → строковый срез |
&OsStr | str | Ссылка на OsStr → строковый срез (если валидный UTF-8) |
&OsString | str | Ссылка на OsString → строковый срез (если валидный UTF-8) |
&Path | str | Ссылка на Path → строковый срез |
&PathBuf | str | Ссылка на PathBuf → строковый срез |
String | str | String → строковый срез |
OsString | str | OsString → строковый срез (если валидный UTF-8) |
PathBuf | str | PathBuf → строковый срез |
Cow<'_, B> | B | Clone-on-write → ссылка на содержимое |
Box<T> | T | Box → ссылка на содержимое |
Rc<T> | T | Rc → ссылка на содержимое |
Arc<T> | T | Arc → ссылка на содержимое |
Vec<T> | [T] | Vec → срез |
&Vec<T> | [T] | Ссылка на Vec → срез |
&mut Vec<T> | [T] | Изменяемая ссылка на Vec → срез |
[T; N] | [T] | Массив → срез |
&[T; N] | [T] | Ссылка на массив → срез |
&mut [T; N] | [T] | Изменяемая ссылка на массив → срез |
Cell<T> | T | Cell → неизменяемая ссылка на содержимое |
RefCell<T> | T | RefCell → неизменяемая ссылка на содержимое |
Mutex<T> | T | Mutex → неизменяемая ссылка на содержимое |
RwLock<T> | T | RwLock → неизменяемая ссылка на содержимое |
Трейт From
#![allow(unused)] fn main() { pub trait From<T>: Sized { // Обязательный метод fn from(value: T) -> Self; } }
Используется для преобразований значение-в-значение с потреблением входного значения. Является обратным к Into.
Всегда следует предпочитать реализацию From вместо Into, потому что реализация From автоматически предоставляет реализацию Into благодаря обобщённой реализации в стандартной библиотеке.
Реализуйте Into только при работе с версиями до Rust 1.41 и преобразовании в тип за пределами текущего крейта. From не мог выполнять такие преобразования в более ранних версиях из-за правил сиротства Rust. Смотрите Into для получения более подробной информации.
Предпочитайте использование Into вместо From при указании трейт-границ для обобщённой функции, чтобы гарантировать, что типы, которые реализуют только Into, также могут быть использованы.
Трейт From также очень полезен при обработке ошибок. При создании функции, которая может завершиться неудачей, возвращаемый тип обычно имеет форму Result<T, E>. From упрощает обработку ошибок, позволяя функции возвращать единственный тип ошибки, который инкапсулирует несколько типов ошибок. Смотрите раздел "Примеры" и книгу для более подробной информации.
Примечание: Этот трейт не должен завершаться неудачей. Трейт From предназначен для безупречных преобразований. Если преобразование может завершиться неудачей или не является безупречным, используйте TryFrom.
Обобщённые реализации
From<T> for UподразумеваетInto<U> for TFromрефлексивен, что означает, чтоFrom<T> for Tреализован
Когда реализовывать From
Хотя нет технических ограничений на то, какие преобразования могут быть выполнены с помощью реализации From, общее ожидание заключается в том, что преобразования обычно должны быть ограничены следующим:
-
Преобразование безупречно: если преобразование может завершиться неудачей, используйте вместо этого
TryFrom; не предоставляйте реализациюFrom, которая паникует. -
Преобразование без потерь: семантически оно не должно терять или отбрасывать информацию. Например, существует
i32: From<u16>, где исходное значение может быть восстановлено с помощьюu16: TryFrom<i32>. И существуетString: From<&str>, где вы можете получить что-то эквивалентное исходному значению черезDeref. НоFromнельзя использовать для преобразования изu32вu16, поскольку это не может быть успешным без потерь. (Здесь есть некоторый простор для информации, которая не считается семантически значимой. Например, существуетBox<[T]>: From<Vec<T>>, даже если он может не сохранять ёмкость, подобно тому как два вектора могут быть равны, несмотря на разную ёмкость.) -
Преобразование сохраняет значение: концептуальный вид и значение результирующего значения одинаковы, даже если тип Rust и техническое представление могут отличаться. Например,
-1_i8 as u8выполняется без потерь, поскольку приведение обратно может восстановить исходное значение, но это преобразование недоступно черезFrom, потому что-1и255являются разными концептуальными значениями (несмотря на идентичные битовые шаблоны технически). Ноf32: From<i16>доступно, потому что1_i16и1.0_f32концептуально представляют одно и то же вещественное число (несмотря на очень разные битовые шаблоны технически).String: From<char>доступно, потому что оба представляют текст, ноString: From<u32>недоступно, поскольку1(число) и"1"(текст) слишком различны. (Преобразование значений в текст вместо этого покрывается трейтомDisplay.) -
Преобразование очевидно: это единственное разумное преобразование между двумя типами. В противном случае лучше иметь именованный метод или конструктор, как, например,
str::as_bytesявляется методом и как целые числа имеют методыu32::from_ne_bytes,u32::from_le_bytesиu32::from_be_bytes, ни один из которых не является реализациейFrom. В то же время существует только один разумный способ обернутьIpv6AddrвIpAddr, поэтому существуетIpAddr: From<Ipv6Addr>.
Примеры
String реализует From<&str>:
Явное преобразование из &str в String выполняется следующим образом:
#![allow(unused)] fn main() { let string = "hello".to_string(); let other_string = String::from("hello"); assert_eq!(string, other_string); }
При обработке ошибок часто полезно реализовать From для вашего собственного типа ошибки. Преобразуя базовые типы ошибок в наш собственный пользовательский тип ошибки, который инкапсулирует базовый тип ошибки, мы можем возвращать единственный тип ошибки без потери информации о базовой причине. Оператор ? автоматически преобразует базовый тип ошибки в наш пользовательский тип ошибки с помощью From::from.
#![allow(unused)] fn main() { use std::fs; use std::io; use std::num; enum CliError { IoError(io::Error), ParseError(num::ParseIntError), } impl From<io::Error> for CliError { fn from(error: io::Error) -> Self { CliError::IoError(error) } } impl From<num::ParseIntError> for CliError { fn from(error: num::ParseIntError) -> Self { CliError::ParseError(error) } } fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> { let mut contents = fs::read_to_string(&file_name)?; let num: i32 = contents.trim().parse()?; Ok(num) } }
Обязательные методы
1.0.0 · Source
#![allow(unused)] fn main() { fn from(value: T) -> Self }
Преобразует в этот тип из входного типа.
Совместимость с dyn
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью", поэтому этот трейт не является объектно-безопасным.
Сводная таблица реализаций трейта From<T>
Примитивные типы и числовые преобразования
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
bool | i8, i16, i32, i64, i128, u8, u16, u32, u64, u128 | 0 → false, любое другое значение → true |
f32 | i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f64 | Числовое преобразование с плавающей точкой |
f64 | i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32 | Числовое преобразование с плавающей точкой |
i8 | bool | false → 0, true → 1 |
i16 | bool, i8, u8 | Числовое преобразование |
i32 | bool, i8, u8, i16, u16, char | Числовое преобразование, char → Unicode scalar value |
i64 | bool, i8, u8, i16, u16, i32, u32, char | Числовое преобразование |
i128 | Все меньшие целые и bool, char | Числовое преобразование |
u8 | bool, char (только значения 0-255) | false → 0, true → 1, char → byte value |
u16 | bool, u8, char | Числовое преобразование, char → Unicode scalar value |
u32 | bool, u8, u16, char | Числовое преобразование, char → Unicode scalar value |
u64 | bool, u8, u16, u32, char | Числовое преобразование |
u128 | Все меньшие беззнаковые целые и bool, char | Числовое преобразование |
Строковые типы
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
String | &str, &mut str, char, Box<str> | Создание owned строки из различных строковых представлений |
Box<str> | String, &str, &mut str, Box<&str> | Создание boxed строкового среза |
Cow<'_, str> | String, &str, &mut str | Создание clone-on-write строки |
Arc<str> | String, &str | Создание атомарно подсчитываемой строки |
Rc<str> | String, &str | Создание подсчитываемой строки |
Коллекции и контейнеры
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
Vec<T> | VecDeque<T>, BinaryHeap<T>, LinkedList<T>, [T; N], Box<[T]> | Преобразование между коллекциями |
VecDeque<T> | Vec<T>, [T; N] | Создание двусторонней очереди |
BinaryHeap<T> | Vec<T> | Создание двоичной кучи |
LinkedList<T> | Vec<T> | Создание связного списка |
Box<[T]> | Vec<T>, [T; N], Box<[T; N]> | Создание boxed среза |
Vec<u8> | String | Строка → вектор байтов (UTF-8) |
Умные указатели и ссылки
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
Box<T> | T, Rc<T>, Arc<T>, Pin<P> | Создание boxed значения |
Rc<T> | Box<T>, Arc<T>, T | Создание подсчитываемой ссылки |
Arc<T> | Box<T>, Rc<T>, T | Создание атомарно подсчитываемой ссылки |
Pin<P> | P | Закрепление указателя |
&[T] | &[T; N] | Массив → срез |
&mut [T] | &mut [T; N] | Изменяемый массив → изменяемый срез |
&str | &String | Ссылка на String → строковый срез |
Option и Result
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
Option<T> | T (через Some) | Значение → Some(value) |
Result<T, E> | T (через Ok) | Значение → Ok(value) |
Сетевые типы
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
IpAddr | Ipv4Addr, Ipv6Addr | Конкретный IP → общий IP адрес |
SocketAddr | SocketAddrV4, SocketAddrV6 | Конкретный socket → общий socket адрес |
Системные типы
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
CString | Vec<u8>, &[u8], &str | Создание C-совместимой строки |
OsString | String, &str | Создание OS-специфичной строки |
PathBuf | String, &str, OsString | Создание пути файловой системы |
Специальные типы
| Целевой тип | Исходный тип | Описание преобразования |
|---|---|---|
NonNull<T> | &T, &mut T | Ссылка → ненулевой указатель |
Cell<T> | T | Значение → cell |
RefCell<T> | T | Значение → ref cell |
Mutex<T> | T | Значение → mutex guard |
RwLock<T> | T | Значение → rwlock |
Трейт Into
#![allow(unused)] fn main() { pub trait Into<T>: Sized { // Обязательный метод fn into(self) -> T; } }
Преобразование значение-в-значение, которое потребляет входное значение. Противоположность From.
Следует избегать реализации Into и вместо этого реализовывать From. Реализация From автоматически предоставляет реализацию Into благодаря обобщённой реализации в стандартной библиотеке.
Предпочитайте использование Into вместо From при указании трейт-границ для обобщённой функции, чтобы гарантировать, что типы, которые реализуют только Into, также могут быть использованы.
Примечание: Этот трейт не должен завершаться неудачей. Если преобразование может завершиться неудачей, используйте
TryInto.
Обобщённые реализации
From<T> for UподразумеваетInto<U> for TIntoрефлексивен, что означает, чтоInto<T> for Tреализован
Реализация Into для преобразований во внешние типы в старых версиях Rust
До Rust 1.41, если целевой тип не был частью текущего крейта, то нельзя было реализовать From напрямую. Например, рассмотрим этот код:
#![allow(unused)] fn main() { struct Wrapper<T>(Vec<T>); impl<T> From<Wrapper<T>> for Vec<T> { fn from(w: Wrapper<T>) -> Vec<T> { w.0 } } }
Этот код не компилировался в старых версиях языка, потому что правила сиротства Rust были немного более строгими. Чтобы обойти это, можно было реализовать Into напрямую:
#![allow(unused)] fn main() { struct Wrapper<T>(Vec<T>); impl<T> Into<Vec<T>> for Wrapper<T> { fn into(self) -> Vec<T> { self.0 } } }
Важно понимать, что Into не предоставляет реализацию From (в отличие от From, который предоставляет Into). Поэтому вы всегда должны пытаться реализовать From и затем возвращаться к Into, если From не может быть реализован.
Примеры
String реализует Into<Vec<u8>>:
Чтобы выразить, что мы хотим, чтобы обобщённая функция принимала все аргументы, которые могут быть преобразованы в указанный тип T, мы можем использовать трейт-границу Into<T>. Например: функция is_hello принимает все аргументы, которые могут быть преобразованы в Vec<u8>.
#![allow(unused)] fn main() { fn is_hello<T: Into<Vec<u8>>>(s: T) { let bytes = b"hello".to_vec(); assert_eq!(bytes, s.into()); } let s = "hello".to_string(); is_hello(s); }
Обязательные методы
1.0.0 · Source
#![allow(unused)] fn main() { fn into(self) -> T }
Преобразует этот тип в (обычно выводимый) входной тип.
Совместимость с dyn
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью", поэтому этот трейт не является объектно-безопасным.
Реализаторы
1.0.0 (const: unstable) · Source
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
Объяснение реализации
Приведённая выше обобщённая реализация означает:
Для любых типов T и U, если U реализует From<T>, то T автоматически реализует Into<U>
Это ключевая особенность взаимосвязи между From и Into - она обеспечивает автоматическую симметрию преобразований.
Примеры автоматических реализаций:
#![allow(unused)] fn main() { // Поскольку String реализует From<&str> // &str автоматически реализует Into<String> let s: String = "hello".into(); // Работает благодаря автоматической реализации // Поскольку Vec<u8> реализует From<String> // String автоматически реализует Into<Vec<u8>> let bytes: Vec<u8> = "hello".to_string().into(); // Преобразование String в Vec<u8> }
Практическое следствие:
Благодаря этой обобщённой реализации, достаточно реализовать только From, и соответствующая реализация Into будет предоставлена автоматически. Это предотвращает дублирование кода и обеспечивает согласованность преобразований.
Трейт TryFrom
#![allow(unused)] fn main() { pub trait TryFrom<T>: Sized { type Error; // Обязательный метод fn try_from(value: T) -> Result<Self, Self::Error>; } }
Простые и безопасные преобразования типов, которые могут завершиться неудачей контролируемым образом в некоторых обстоятельствах. Является обратным к TryInto.
Это полезно, когда вы выполняете преобразование типа, которое может тривиально завершиться успехом, но также может потребовать специальной обработки. Например, нет способа преобразовать i64 в i32 с помощью трейта From, потому что i64 может содержать значение, которое i32 не может представить, и поэтому преобразование приведёт к потере данных. Это можно обработать путём усечения i64 до i32, простого возврата i32::MAX или каким-либо другим методом. Трейт From предназначен для безупречных преобразований, поэтому трейт TryFrom информирует программиста, когда преобразование типа может пойти плохо, и позволяет ему решить, как с этим справиться.
Обобщённые реализации
TryFrom<T> for UподразумеваетTryInto<U> for Ttry_fromрефлексивен, что означает, чтоTryFrom<T> for Tреализован и не может завершиться неудачей - связанный типErrorдля вызоваT::try_from()на значении типаTявляетсяInfallible. Когда тип!стабилизируется,Infallibleи!будут эквивалентны.
Предпочитайте использование TryInto вместо TryFrom при указании трейт-границ для обобщённой функции, чтобы гарантировать, что типы, которые реализуют только TryInto, также могут быть использованы.
TryFrom<T> может быть реализован следующим образом:
#![allow(unused)] fn main() { struct GreaterThanZero(i32); impl TryFrom<i32> for GreaterThanZero { type Error = &'static str; fn try_from(value: i32) -> Result<Self, Self::Error> { if value <= 0 { Err("GreaterThanZero only accepts values greater than zero!") } else { Ok(GreaterThanZero(value)) } } } }
Примеры
Как описано, i32 реализует TryFrom<i64>:
#![allow(unused)] fn main() { let big_number = 1_000_000_000_000i64; // Тихо усекает `big_number`, требует обнаружения // и обработки усечения после факта. let smaller_number = big_number as i32; assert_eq!(smaller_number, -727379968); // Возвращает ошибку, потому что `big_number` слишком велик, // чтобы поместиться в `i32`. let try_smaller_number = i32::try_from(big_number); assert!(try_smaller_number.is_err()); // Возвращает `Ok(3)`. let try_successful_smaller_number = i32::try_from(3); assert!(try_successful_smaller_number.is_ok()); }
Обязательные связанные типы
1.34.0 · Source
#![allow(unused)] fn main() { type Error }
Тип, возвращаемый в случае ошибки преобразования.
Обязательные методы
1.34.0 · Source
#![allow(unused)] fn main() { fn try_from(value: T) -> Result<Self, Self::Error> }
Выполняет преобразование.
Совместимость с dyn
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью", поэтому этот трейт не является объектно-безопасным.
Реализаторы
Сводная таблица реализаций трейта TryFrom<T>
| Целевой тип | Исходный тип | Тип ошибки | Условия успешного преобразования |
|---|---|---|---|
i8 | i16, i32, i64, i128, isize | TryFromIntError | Значение в пределах i8::MIN..=i8::MAX |
i16 | i32, i64, i128, isize | TryFromIntError | Значение в пределах i16::MIN..=i16::MAX |
i32 | i64, i128, isize | TryFromIntError | Значение в пределах i32::MIN..=i32::MAX |
i64 | i128 | TryFromIntError | Значение в пределах i64::MIN..=i64::MAX |
u8 | i8, i16, i32, i64, i128, isize, u16, u32, u64, u128, usize | TryFromIntError | Для знаковых: значение ≥ 0 и ≤ u8::MAXДля беззнаковых: значение ≤ u8::MAX |
u16 | i16, i32, i64, i128, isize, u32, u64, u128, usize | TryFromIntError | Для знаковых: значение ≥ 0 и ≤ u16::MAXДля беззнаковых: значение ≤ u16::MAX |
u32 | i32, i64, i128, isize, u64, u128, usize | TryFromIntError | Для знаковых: значение ≥ 0 и ≤ u32::MAXДля беззнаковых: значение ≤ u32::MAX |
u64 | i64, i128, u128 | TryFromIntError | Для знаковых: значение ≥ 0 и ≤ u64::MAXДля беззнаковых: значение ≤ u64::MAX |
usize | i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128 | TryFromIntError | Зависит от архитектуры платформы |
isize | i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize | TryFromIntError | Зависит от архитектуры платформы |
char | u8 | CharTryFromError | Значение в пределах 0..=0x7F (валидный ASCII) |
CString | Vec<u8> | FromVecWithNulError | Вектор не содержит нулевых байтов |
OsString | PathBuf | (нет ошибки) | Всегда успешно |
PathBuf | OsString | (нет ошибки) | Всегда успешно |
String | &str | (нет ошибки) | Всегда успешно |
Vec<T> | VecDeque<T>, BinaryHeap<T>, LinkedList<T>, Box<[T]> | (нет ошибки) | Всегда успешно |
Дополнительные реализации для примитивных типов
Преобразования между целыми числами
- Все комбинации между знаковыми и беззнаковыми целыми
- Проверка на переполнение и отрицательные значения
- Возвращает
TryFromIntErrorпри нарушении границ
Строковые преобразования
#![allow(unused)] fn main() { // char из u8 (только ASCII) let ascii_char = char::try_from(65u8).unwrap(); // 'A' let invalid_char = char::try_from(255u8); // Err(CharTryFromError) // CString из Vec<u8> let valid_vec = vec![b'h', b'i']; let cstring = CString::try_from(valid_vec).unwrap(); let invalid_vec = vec![0, 1, 2]; let error = CString::try_from(invalid_vec); // Err(FromVecWithNulError) }
Особенности обработки ошибок
TryFromIntError
- Для всех числовых преобразований между целыми типами
- Не содержит дополнительной информации о причине ошибки
- Реализует
Debug,Display,Error
CharTryFromError
- Специфична для преобразований в
char - Возникает при невалидных значениях Unicode
FromVecWithNulError
- Для преобразований в
CString - Возникает при наличии нулевых байтов в векторе
- Предоставляет метод
into_bytes()для восстановления исходных данных
Трейт TryInto
#![allow(unused)] fn main() { pub trait TryInto<T>: Sized { type Error; // Обязательный метод fn try_into(self) -> Result<T, Self::Error>; } }
Попытка преобразования, которая потребляет self и может быть как дорогой, так и дешёвой.
Авторам библиотек обычно не следует напрямую реализовывать этот трейт, а следует предпочитать реализацию трейта TryFrom, который предлагает большую гибкость и предоставляет эквивалентную реализацию TryInto бесплатно, благодаря обобщённой реализации в стандартной библиотеке. Для получения дополнительной информации об этом см. документацию для Into.
Предпочитайте использование TryInto вместо TryFrom при указании трейт-границ для обобщённой функции, чтобы гарантировать, что типы, которые реализуют только TryInto, также могут быть использованы.
Реализация TryInto
Это страдает от тех же ограничений и обоснований, что и реализация Into, см. там для подробностей.
Обязательные связанные типы
1.34.0 · Source
#![allow(unused)] fn main() { type Error }
Тип, возвращаемый в случае ошибки преобразования.
Обязательные методы
1.34.0 · Source
#![allow(unused)] fn main() { fn try_into(self) -> Result<T, Self::Error> }
Выполняет преобразование.
Совместимость с dyn
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью", поэтому этот трейт не является объектно-безопасным.
Реализаторы
1.34.0 (const: unstable) · Source
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Объяснение реализации
Приведённая выше обобщённая реализация означает:
Для любых типов T и U, если U реализует TryFrom<T>, то T автоматически реализует TryInto<U>
Эта реализация обеспечивает автоматическую симметрию между TryFrom и TryInto, аналогично связи между From и Into.
Практическое следствие:
Благодаря этой обобщённой реализации, достаточно реализовать только TryFrom, и соответствующая реализация TryInto будет предоставлена автоматически.
Примеры использования
Базовое использование
#![allow(unused)] fn main() { use std::convert::TryInto; let x: i32 = 5; let y: u8 = x.try_into().unwrap(); // Успешно для 5 println!("{}", y); // 5 let x: i32 = 256; let y: Result<u8, _> = x.try_into(); // Ошибка - значение слишком большое для u8 assert!(y.is_err()); }
Использование в обобщённых функциях
#![allow(unused)] fn main() { use std::convert::TryInto; fn process_number<T, U>(value: T) -> Result<U, U::Error> where T: TryInto<U>, { value.try_into() } let result: Result<u8, _> = process_number(100i32); assert_eq!(result, Ok(100)); let result: Result<u8, _> = process_number(1000i32); assert!(result.is_err()); }
Цепочка преобразований с обработкой ошибок
#![allow(unused)] fn main() { use std::convert::TryInto; fn convert_safely(value: i64) -> Result<i32, Box<dyn std::error::Error>> { let medium: i32 = value.try_into()?; let small: i16 = medium.try_into()?; Ok(small) } println!("{:?}", convert_safely(1000)); // Ok(1000) println!("{:?}", convert_safely(1_000_000_000)); // Err (переполнение i16) }
Сравнение с TryFrom
TryFrom (предпочтительный для реализации)
#![allow(unused)] fn main() { impl TryFrom<i32> for u8 { type Error = TryFromIntError; fn try_from(value: i32) -> Result<Self, Self::Error> { // логика преобразования } } }
TryInto (автоматически предоставляется)
#![allow(unused)] fn main() { // Автоматически генерируется из TryFrom let x: i32 = 100; let y: u8 = u8::try_from(x).unwrap(); // Явный вызов TryFrom let z: u8 = x.try_into().unwrap(); // Автоматический вызов TryInto }
Обработка различных типов ошибок
Поскольку TryInto наследует тип ошибки от соответствующей реализации TryFrom, можно обрабатывать различные виды ошибок преобразования:
#![allow(unused)] fn main() { use std::convert::{TryInto, TryFrom}; // Числовые преобразования match 1000i32.try_into() as Result<u8, _> { Ok(val) => println!("Успех: {}", val), Err(_) => println!("Число слишком большое"), } // Строковые преобразования match vec![b'h', b'i', 0].try_into() as Result<std::ffi::CString, _> { Ok(cstr) => println!("Успешное CString"), Err(e) => println!("Ошибка создания CString: {:?}", e), } }
Ключевые преимущества
Согласованность с существующим кодом
- Единообразный API с
Into/From - Предсказуемое поведение
Безопасность типов
- Проверки во время компиляции
- Явная обработка возможных ошибок
Гибкость использования
- Может использоваться в трейт-границах
- Поддерживает цепочки преобразований
- Интегрируется с оператором
?
Перечисление Infallible
#![allow(unused)] fn main() { pub enum Infallible {} }
Тип ошибки для ошибок, которые никогда не могут произойти.
Поскольку это перечисление не имеет вариантов, значение этого типа никогда не может фактически существовать. Это может быть полезно для обобщённых API, которые используют Result и параметризуют тип ошибки, чтобы указать, что результат всегда Ok.
Например, трейт TryFrom (преобразование, которое возвращает Result) имеет обобщённую реализацию для всех типов, где существует обратная реализация Into.
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, { type Error = Infallible; fn try_from(value: U) -> Result<Self, Infallible> { Ok(U::into(value)) // Никогда не возвращает `Err` } } }
Совместимость с будущими версиями
Это перечисление имеет ту же роль, что и тип ! ("never"), который нестабилен в этой версии Rust. Когда ! стабилизируется, мы планируем сделать Infallible псевдонимом типа для него:
#![allow(unused)] fn main() { pub type Infallible = !; }
… и в конечном итоге объявить Infallible устаревшим.
Однако есть один случай, когда синтаксис ! может использоваться до того, как ! стабилизируется как полноценный тип: в позиции возвращаемого типа функции. В частности, возможны реализации для двух разных типов указателей на функции:
#![allow(unused)] fn main() { trait MyTrait {} impl MyTrait for fn() -> ! {} impl MyTrait for fn() -> std::convert::Infallible {} }
Поскольку Infallible является перечислением, этот код действителен. Однако когда Infallible станет псевдонимом для типа never, две реализации начнут перекрываться и поэтому будут запрещены правилами когерентности трейтов языка.
Реализации трейтов
Сводная таблица реализаций трейтов для Infallible
| Трейт | Метод(ы) | Описание реализации |
|---|---|---|
Clone | fn clone(&self) -> Self | Не может быть вызван (нет значений) |
Copy | (маркерный трейт) | Разрешает копирование семантики |
Debug | fn fmt(&self, f: &mut Formatter<'_>) -> Result | Форматирование для отладки |
Display | fn fmt(&self, f: &mut Formatter<'_>) -> Result | Пользовательское форматирование |
Error | source(), description(), cause() | Реализация для типа ошибки |
Eq | fn eq(&self, _: &Self) -> bool | Сравнение на равенство |
Hash | fn hash<H: Hasher>(&self, _: &mut H) | Хеширование значения |
Ord | cmp(), max(), min(), clamp() | Сравнение для упорядочивания |
PartialEq | fn eq(&self, _: &Self) -> bool | Частичное равенство |
PartialOrd | partial_cmp(), lt(), le(), gt(), ge() | Частичное упорядочивание |
StructuralEq | (маркерный трейт) | Для сопоставления с образцом |
StructuralPartialEq | (маркерный трейт) | Для частичного сопоставления |
Особенности реализаций
Все реализации безусловны
Поскольку Infallible не имеет значений, все методы могут быть реализованы без фактического выполнения кода.
Маркерные трейты
Copy,StructuralEq,StructuralPartialEq- маркерные трейты без методов- Гарантируют определённое поведение на уровне типажа
Трейты ошибок
Error реализован, что позволяет использовать Infallible как тип ошибки в Result, где ошибка никогда не происходит.
Сравнение и хеширование
Все методы сравнения и хеширования тривиальны, так как никогда не вызываются.
Практическое использование
В обобщённых API
#![allow(unused)] fn main() { fn always_succeeds() -> Result<i32, Infallible> { Ok(42) // Ошибка никогда не может произойти } }
С TryFrom/TryInto
#![allow(unused)] fn main() { // Преобразование, которое никогда не fails let x: i32 = i32::try_from(10u32).unwrap(); // Можно безопасно использовать unwrap }
В пользовательских типах
#![allow(unused)] fn main() { enum MyResult<T> { Ok(T), Err(Infallible), // Указывает, что ошибка невозможна } }
Будущее развитие
Infallible является временным решением до стабилизации типа ! (never type). После стабилизации все текущие использования Infallible будут автоматически перенаправлены на !.
Функция identity
#![allow(unused)] fn main() { pub const fn identity<T>(x: T) -> T }
Функция тождества.
Две важные вещи, которые следует отметить об этой функции:
- Она не всегда эквивалентна замыканию типа
|x| x, поскольку замыкание может приводитьxк другому типу. - Она перемещает входное значение
x, переданное в функцию.
Хотя может показаться странным иметь функцию, которая просто возвращает входные данные, есть некоторые интересные варианты использования.
Примеры
Использование identity для "ничего не делания" в последовательности других, интересных функций:
#![allow(unused)] fn main() { use std::convert::identity; fn manipulation(x: u32) -> u32 { // Предположим, что добавление единицы - это интересная функция. x + 1 } let _arr = &[identity, manipulation]; }
Использование identity как базового случая "ничего не делания" в условном выражении:
#![allow(unused)] fn main() { use std::convert::identity; let condition = true; // или false let do_stuff = if condition { manipulation } else { identity }; // Делаем более интересные вещи... let results = do_stuff(42); }
Использование identity для сохранения вариантов Some итератора Option<T>:
#![allow(unused)] fn main() { use std::convert::identity; let iter = [Some(1), None, Some(3)].into_iter(); let filtered = iter.filter_map(identity).collect::<Vec<_>>(); assert_eq!(vec![1, 3], filtered); }
Использование для преобразования типажа в объект типажа:
#![allow(unused)] fn main() { use std::convert::identity; trait MyTrait {} struct MyStruct; impl MyTrait for MyStruct {} let obj: Box<dyn MyTrait> = Box::new(MyStruct); // identity может помочь в ситуациях с приведением типов объектов типажей }
Использование в комбинаторах высшего порядка:
#![allow(unused)] fn main() { use std::convert::identity; let numbers = vec![1, 2, 3, 4, 5]; // Иногда нужно передать функцию-преобразователь, но не менять значения let unchanged: Vec<i32> = numbers.into_iter().map(identity).collect(); }
Особенности реализации
Константная функция
Функция помечена как const, что позволяет использовать её в константных контекстах:
#![allow(unused)] fn main() { const RESULT: i32 = identity(42); }
Сохранение владения
Функция принимает значение по владению и возвращает его, что полезно для семантики перемещения:
#![allow(unused)] fn main() { let s = String::from("hello"); let s2 = identity(s); // s перемещается, а не заимствуется }
Отсутствие приведения типов
В отличие от замыканий, identity не выполняет неявного приведения типов:
#![allow(unused)] fn main() { let x: i32 = 42; // Замыкание может привести к &i32, а identity - нет let closure: &i32 = (|x| x)(&x); // let wrong = identity(&x); // Это не скомпилируется, если ожидается i32 }
Практические сценарии использования
Заполнитель в API
#![allow(unused)] fn main() { fn process_data<T, F>(data: T, transformer: F) -> T where F: FnOnce(T) -> T, { transformer(data) } // Использование без преобразования let result = process_data(100, identity); }
Фильтрация Option значений
#![allow(unused)] fn main() { use std::convert::identity; let options = vec![Some("hello"), None, Some("world")]; let present: Vec<&str> = options.into_iter().filter_map(identity).collect(); }
Базовый случай в рекурсивных алгоритмах
#![allow(unused)] fn main() { fn transform_data<F>(data: Vec<i32>, transform: F) -> Vec<i32> where F: Fn(i32) -> i32, { if data.is_empty() { vec![] } else { // Используем identity как преобразование по умолчанию data.into_iter().map(transform).collect() } } // Использование без изменений let data = vec![1, 2, 3]; let result = transform_data(data, identity); }
Производительность
Благодаря тому, что функция тривиальна, компилятор обычно полностью оптимизирует её вызовы, не создавая накладных расходов во время выполнения.
Модуль future
Базовая асинхронная функциональность.
Для получения дополнительной информации об асинхронном программировании в Rust обратитесь к основным ключевым словам async и await, а также к книге по асинхронному программированию.
Макросы
join
Экспериментальный Одновременно опрашивает несколько фьючеров, возвращая кортеж со всеми результатами после их завершения.
Структуры
Pending
Создает фьючер, который никогда не разрешается, представляя вычисление, которое никогда не завершается.
PollFn
Фьючер, который оборачивает функцию, возвращающую Poll.
Ready
Фьючер, который немедленно готов со значением.
Трейты
Future
Фьючер представляет асинхронное вычисление, обычно получаемое с помощью async.
IntoFuture
Преобразование в Future.
AsyncDrop
Экспериментальный Асинхронная версия трейта Drop.
Функции
pending
Создает фьючер, который никогда не разрешается, представляя вычисление, которое никогда не завершается.
poll_fn
Создает фьючер, который оборачивает функцию, возвращающую Poll.
ready
Создает фьючер, который немедленно готов со значением.
async_drop_in_place
⚠ Экспериментальный Асинхронное удаление.
Future в Rust: концепция и механизм работы
Что такое Future?
Future (фьючер, будущее значение) - это асинхронный аналог
OptionилиResult, который представляет значение, которое может быть доступно в некоторый момент в будущем.Проще говоря:
- Future = обещание результата, который будет вычислен асинхронно
- Это значение, которое "еще не готово", но будет доступно позже
Базовое определение
#![allow(unused)] fn main() { pub trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; } pub enum Poll<T> { Ready(T), Pending, } }
Как работает Future?
1. Ленивая природа
Фьючеры не выполняются автоматически - они должны быть явно "запущены" с помощью исполнителя (executor):
#![allow(unused)] fn main() { // Фьючер создан, но не выполняется let future = async { 42 }; // Чтобы выполнить, нужен исполнитель: // let result = executor::block_on(future); }
2. Механизм опроса (Polling)
Система работает по принципу "опроса":
- Исполнитель периодически "опрашивает" фьючер:
future.poll() - Фьючер возвращает:
Poll::Ready(value)- результат готовPoll::Pending- результат еще не готов
3. Await - синтаксический сахар
Ключевое слово await скрывает сложность опроса:
#![allow(unused)] fn main() { async fn example() { let result = some_async_function().await; // Эквивалентно многократным вызовам poll() до получения Ready } }
Жизненный цикл Future
Создание → Опрос (Pending) → ... → Опрос (Ready) → Завершение
↑
└── Исполнитель повторяет опрос
Практический пример
#![allow(unused)] fn main() { use std::future::Future; use std::task::{Context, Poll}; use std::pin::Pin; struct SimpleFuture { completed: bool, } impl Future for SimpleFuture { type Output = i32; fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { if self.completed { Poll::Ready(42) } else { self.completed = true; Poll::Pending } } } }
Эко-система
Future является частью трехуровневой системы:
- Future - базовый трейт
- Executor - планировщик выполнения
- Reactor/Waker - система уведомлений о готовности
Эта система позволяет писать высокопроизводительные асинхронные приложения с минимальными накладными расходами.
Macros
Макрос join
#![allow(unused)] fn main() { pub macro join($($fut:expr),+ $(,)?) { ... } }
🔬 Это экспериментальный API, доступный только в ночных сборках. (
future_join#91642)
Одновременно опрашивает несколько фьючеров, возвращая кортеж со всеми результатами после их завершения.
Хотя join!(a, b).await похоже на (a.await, b.await), макрос join! опрашивает оба фьючера конкурентно и поэтому более эффективен.
Примеры
#![allow(unused)] #![feature(future_join)] fn main() { use std::future::join; async fn one() -> usize { 1 } async fn two() -> usize { 2 } let x = join!(one(), two()).await; assert_eq!(x, (1, 2)); }
join! является вариативным, поэтому вы можете передавать любое количество фьючеров:
#![allow(unused)] #![feature(future_join)] fn main() { use std::future::join; async fn one() -> usize { 1 } async fn two() -> usize { 2 } async fn three() -> usize { 3 } let x = join!(one(), two(), three()).await; assert_eq!(x, (1, 2, 3)); }
join! является вариативным, поэтому вы можете передавать любое количество фьючеров:
#![allow(unused)] #![feature(future_join)] fn main() { use std::future::join; async fn one() -> usize { 1 } async fn two() -> usize { 2 } async fn three() -> usize { 3 } let x = join!(one(), two(), three()).await; assert_eq!(x, (1, 2, 3)); }
Struct
Структура Pending
#![allow(unused)] fn main() { pub struct Pending<T> { /* приватные поля */ } }
Создает фьючер, который никогда не разрешается, представляя вычисление, которое никогда не завершается.
Эта структура создается с помощью функции pending(). См. ее документацию для получения дополнительной информации.
Реализации трейтов
impl<T> Clone for Pending<T>
#![allow(unused)] fn main() { fn clone(&self) -> Pending<T> }
Возвращает копию значения. Подробнее
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет присвоение копированием из источника. Подробнее
impl<T> Debug for Pending<T>
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с использованием заданного форматировщика. Подробнее
impl<T> Future for Pending<T>
#![allow(unused)] fn main() { type Output = T //Тип значения, производимого при завершении. fn poll(self: Pin<&mut Pending<T>>, _: &mut Context<'_>) -> Poll<T> }
Пытается разрешить фьючер в конечное значение, регистрируя текущую задачу для пробуждения, если значение еще не доступно. Подробнее
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<T> Freeze for Pending<T> impl<T> RefUnwindSafe for Pending<T> impl<T> Send for Pending<T> impl<T> Sync for Pending<T> impl<T> Unpin for Pending<T> impl<T> UnwindSafe for Pending<T> }
Общие реализации (Blanket Implementations)
impl<T> Any for T
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, fn type_id(&self) -> TypeId }
Получает TypeId для self. Подробнее
impl<T> Borrow<T> for T
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, fn borrow(&self) -> &T }
Неизменяемо заимствует у владеемого значения. Подробнее
impl<T> BorrowMut<T> for T
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, fn borrow_mut(&mut self) -> &mut T }
Изменяемо заимствует у владеемого значения. Подробнее
impl<T> CloneToUninit for T
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, unsafe fn clone_to_uninit(&self, dest: *mut u8) }
🔬 Это экспериментальный API, доступный только в ночных сборках. (
clone_to_uninit#126799)
Выполняет присвоение копированием из self в dest. Подробнее
impl<T> From<T> for T
#![allow(unused)] fn main() { impl<T> From<T> for T fn from(t: T) -> T }
Возвращает аргумент без изменений.
impl<T, U> Into<U> for T
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, fn into(self) -> U //Вызывает U::from(self). }
То есть, это преобразование выполняется так, как решила реализация From<T> для U.
impl<F> IntoFuture for F
#![allow(unused)] fn main() { impl<F> IntoFuture for F where F: Future, type Output = <F as Future>::Output //Результат, который фьючер произведет при завершении. type IntoFuture = F //В какой тип фьючера мы преобразуем это значение? fn into_future(self) -> <F as IntoFuture>::IntoFuture //Создает фьючер из значения. }
impl<T> ToOwned for T
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, type Owned = T //Результирующий тип после получения владения. fn to_owned(&self) -> T }
Создает владеемые данные из заимствованных данных, обычно путем клонирования. Подробнее
#![allow(unused)] fn main() { fn clone_into(&self, target: &mut T) }
Использует заимствованные данные для замены владеемых данных, обычно путем клонирования. Подробнее
impl<T, U> TryFrom<U> for T
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, type Error = Infallible //Тип, возвращаемый в случае ошибки преобразования. fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error> //Выполняет преобразование. }
impl<T, U> TryInto<U> for T
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, type Error = <U as TryFrom<T>>::Error //Тип, возвращаемый в случае ошибки преобразования. fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error> //Выполняет преобразование. }
Структура PollFn
#![allow(unused)] fn main() { pub struct PollFn<F> { /* приватные поля */ } }
Фьючер, который оборачивает функцию, возвращающую
Poll.
Эта структура создается с помощью функции poll_fn(). См. ее документацию для получения дополнительной информации.
Реализации трейтов
impl<F> Debug for PollFn<F>
#![allow(unused)] fn main() { impl<F> Debug for PollFn<F> fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с использованием заданного форматировщика. Подробнее
impl<T, F> Future for PollFn<F>
#![allow(unused)] fn main() { impl<T, F> Future for PollFn<F> where F: FnMut(&mut Context<'_>) -> Poll<T>, type Output = T //Тип значения, производимого при завершении. fn poll(self: Pin<&mut PollFn<F>>, cx: &mut Context<'_>) -> Poll<T> }
Пытается разрешить фьючер в конечное значение, регистрируя текущую задачу для пробуждения, если значение еще не доступно. Подробнее
impl<F> Unpin for PollFn<F>
#![allow(unused)] fn main() { impl<F> Unpin for PollFn<F> where F: Unpin, }
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<F> Freeze for PollFn<F> where F: Freeze, impl<F> RefUnwindSafe for PollFn<F> where F: RefUnwindSafe, impl<F> Send for PollFn<F> where F: Send, impl<F> Sync for PollFn<F> where F: Sync, impl<F> UnwindSafe for PollFn<F> where F: UnwindSafe, }
Общие реализации (Blanket Implementations)
impl<T> Any for T
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, fn type_id(&self) -> TypeId }
Получает TypeId для self. Подробнее
impl<T> Borrow<T> for T
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, fn borrow(&self) -> &T }
Неизменяемо заимствует у владеемого значения. Подробнее
impl<T> BorrowMut<T> for T
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, fn borrow_mut(&mut self) -> &mut T }
Изменяемо заимствует у владеемого значения. Подробнее
impl<T> From<T> for T
#![allow(unused)] fn main() { impl<T> From<T> for T` fn from(t: T) -> T //Возвращает аргумент без изменений. }
impl<T, U> Into<U> for T
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, fn into(self) -> U //Вызывает U::from(self). }
То есть, это преобразование выполняется так, как решила реализация From<T> для U.
impl<F> IntoFuture for F
#![allow(unused)] fn main() { impl<F> IntoFuture for F where F: Future, type Output = <F as Future>::Output //Результат, который фьючер произведет при завершении. type IntoFuture = F //В какой тип фьючера мы преобразуем это значение? fn into_future(self) -> <F as IntoFuture>::IntoFuture //Создает фьючер из значения. }
impl<T, U> TryFrom<U> for T
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, type Error = Infallible //Тип, возвращаемый в случае ошибки преобразования. fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error> //Выполняет преобразование. }
impl<T, U> TryInto<U> for T
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, type Error = <U as TryFrom<T>>::Error //Тип, возвращаемый в случае ошибки преобразования. fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error> //Выполняет преобразование. }
Структура Ready
#![allow(unused)] fn main() { pub struct Ready<T>(/* приватные поля */); }
Фьючер, который немедленно готов со значением.
Эта структура создается с помощью функции ready(). См. ее документацию для получения дополнительной информации.
Реализации
impl<T> Ready<T>
#![allow(unused)] fn main() { impl<T> Ready<T> pub fn into_inner(self) -> T //Потребляет `Ready`, возвращая обернутое значение. }
Паника
Вызовет панику, если этот Ready уже был опрошен до завершения.
Примеры
#![allow(unused)] fn main() { use std::future; let a = future::ready(1); assert_eq!(a.into_inner(), 1); }
Реализации трейтов
impl<T> Clone for Ready<T>
#![allow(unused)] fn main() { impl<T> Clone for Ready<T> where T: Clone, fn clone(&self) -> Ready<T> ⓘ }
Возвращает копию значения. Подробнее
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет присвоение копированием из источника. Подробнее
impl<T> Debug for Ready<T>
#![allow(unused)] fn main() { impl<T> Debug for Ready<T> where T: Debug, fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с использованием заданного форматировщика. Подробнее
impl<T> Future for Ready<T>
#![allow(unused)] fn main() { impl<T> Future for Ready<T> type Output = T //Тип значения, производимого при завершении. fn poll(self: Pin<&mut Ready<T>>, _cx: &mut Context<'_>) -> Poll<T> //Пытается разрешить фьючер в конечное значение, регистрируя текущую задачу для пробуждения, если значение еще не доступно. }
impl<T> Unpin for Ready<T>
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<T> Freeze for Ready<T> where T: Freeze, impl<T> RefUnwindSafe for Ready<T> where T: RefUnwindSafe, impl<T> Send for Ready<T> where T: Send, impl<T> Sync for Ready<T> where T: Sync, impl<T> UnwindSafe for Ready<T> where T: UnwindSafe, }
Общие реализации (Blanket Implementations)
impl<T> Any for T
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, fn type_id(&self) -> TypeId }
Получает TypeId для self. Подробнее
impl<T> Borrow<T> for T
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, fn borrow(&self) -> &T }
Неизменяемо заимствует у владеемого значения. Подробнее
impl<T> BorrowMut<T> for T
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, fn borrow_mut(&mut self) -> &mut T }
Изменяемо заимствует у владеемого значения. Подробнее
impl<T> CloneToUninit for T
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, unsafe fn clone_to_uninit(&self, dest: *mut u8) }
🔬 Это экспериментальный API, доступный только в ночных сборках. (
clone_to_uninit#126799)
Выполняет присвоение копированием из self в dest. Подробнее
impl<T> From<T> for T
#![allow(unused)] fn main() { impl<T> From<T> for T fn from(t: T) -> T //Возвращает аргумент без изменений. }
impl<T, U> Into<U> for T
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, fn into(self) -> U //Вызывает U::from(self). }
То есть, это преобразование выполняется так, как решила реализация From<T> для U.
impl<F> IntoFuture for F
#![allow(unused)] fn main() { impl<F> IntoFuture for F where F: Future, type Output = <F as Future>::Output //Результат, который фьючер произведет при завершении. type IntoFuture = F //В какой тип фьючера мы преобразуем это значение? fn into_future(self) -> <F as IntoFuture>::IntoFuture //Создает фьючер из значения. }
impl<T> ToOwned for T
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, type Owned = T //Результирующий тип после получения владения. fn to_owned(&self) -> T //Создает владеемые данные из заимствованных данных, обычно путем клонирования. }
#![allow(unused)] fn main() { fn clone_into(&self, target: &mut T) }
Использует заимствованные данные для замены владеемых данных, обычно путем клонирования. Подробнее
impl<T, U> TryFrom<U> for T
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, type Error = Infallible //Тип, возвращаемый в случае ошибки преобразования. fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error> //Выполняет преобразование. }
impl<T, U> TryInto<U> for T
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, type Error = <U as TryFrom<T>>::Error //Тип, возвращаемый в случае ошибки преобразования. fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error> //Выполняет преобразование. }
Traits
Трейт Future
#![allow(unused)] fn main() { pub trait Future { type Output; // Обязательный метод fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; } }
Фьючер представляет асинхронное вычисление, обычно получаемое с помощью async.
Фьючер - это значение, которое, возможно, еще не завершило вычисление. Такой тип "асинхронного значения" позволяет потоку продолжать выполнять полезную работу, пока он ожидает доступности значения.
Метод poll
Основной метод фьючера, poll, пытается разрешить фьючер в конечное значение. Этот метод не блокирует выполнение, если значение еще не готово. Вместо этого текущая задача планируется к пробуждению, когда можно будет продолжить прогресс путем повторного опроса. Контекст, передаваемый в метод poll, может предоставить Waker - дескриптор для пробуждения текущей задачи.
При работе с фьючером вы обычно не вызываете poll напрямую, а используете .await для получения значения.
Обязательные ассоциированные типы
type Output
Тип значения, производимого при завершении.
Обязательные методы
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
Пытается разрешить фьючер в конечное значение, регистрируя текущую задачу для пробуждения, если значение еще не доступно.
Возвращаемое значение
Эта функция возвращает:
Poll::Pendingесли фьючер еще не готовPoll::Ready(val)с результатомvalэтого фьючера, если он успешно завершился
После того как фьючер завершился, клиенты не должны опрашивать его снова.
Когда фьючер еще не готов, poll возвращает Poll::Pending и сохраняет клон Waker, скопированный из текущего Context. Этот Waker затем будет разбужен, как только фьючер сможет продолжить выполнение. Например, фьючер, ожидающий доступности сокета для чтения, вызовет .clone() на Waker и сохранит его. Когда в другом месте поступает сигнал, указывающий, что сокет доступен для чтения, вызывается Waker::wake и задача сокетного фьючера пробуждается. После пробуждения задачи она должна снова попытаться опросить фьючер, что может привести (или не привести) к получению конечного значения.
Важно отметить, что при многократных вызовах poll только Waker из Context, переданного в последний вызов, должен быть запланирован для получения пробуждения.
Характеристики времени выполнения
Сами по себе фьючеры инертны; они должны активно опрашиваться, чтобы базовое вычисление могло прогрессировать. Это означает, что каждый раз при пробуждении текущей задачи она должна активно переопрашивать ожидающие фьючеры, которые все еще представляют для нее интерес.
Тем не менее, некоторые фьючеры могут представлять значение, которое вычисляется в другой задаче. В этом случае базовое вычисление фьючера просто выступает в качестве канала для значения, вычисляемого этой другой задачей, которая будет выполняться независимо от фьючера. Фьючеры такого типа обычно получаются при порождении новой задачи в асинхронной среде выполнения.
Функция poll не должна вызываться повторно в тесном цикле - вместо этого она должна вызываться только тогда, когда фьючер указывает, что готов к прогрессу (путем вызова wake()). Если вы знакомы с системными вызовами poll(2) или select(2) в Unix, стоит отметить, что фьючеры обычно не страдают от тех же проблем "все пробуждения должны опрашивать все события"; они больше похожи на epoll(4).
Реализация poll должна стремиться возвращаться быстро и не должна блокировать. Быстрое возвращение предотвращает ненужную загрузку потоков или циклов событий. Если заранее известно, что вызов poll может занять много времени, работу следует выгрузить в пул потоков (или что-то подобное), чтобы обеспечить быстрое возвращение из poll.
Паника
После того как фьючер завершился (вернул Ready из poll), повторный вызов его метода poll может вызвать панику, заблокировать выполнение навсегда или вызвать другие виды проблем; трейт Future не накладывает требований на последствия такого вызова. Однако, поскольку метод poll не помечен как unsafe, применяются обычные правила Rust: вызовы никогда не должны вызывать неопределенное поведение (повреждение памяти, неправильное использование небезопасных функций и т.п.), независимо от состояния фьючера.
Реализаторы
#![allow(unused)] fn main() { impl<F> Future for &mut F where F: Future + Unpin + ?Sized, type Output = <F as Future>::Output }
#![allow(unused)] fn main() { impl<F> Future for AssertUnwindSafe<F> where F: Future, type Output = <F as Future>::Output }
#![allow(unused)] fn main() { impl<F, A> Future for Box<F, A> where F: Future + Unpin + ?Sized, A: Allocator, type Output = <F as Future>::Output }
#![allow(unused)] fn main() { impl<P> Future for Pin<P> where P: DerefMut, <P as Deref>::Target: Future, type Output = <F as Future>::Output }
#![allow(unused)] fn main() { impl<T> Future for Exclusive<T> where T: Future + ?Sized, type Output = <F as Future>::Output }
#![allow(unused)] fn main() { impl<T> Future for Pending<T> type Output = T }
#![allow(unused)] fn main() { impl<T> Future for Ready<T> type Output = T }
#![allow(unused)] fn main() { impl<T, F> Future for PollFn<F> where F: FnMut(&mut Context<'_>) -> Poll<T>, type Output = T }
Трейт IntoFuture
#![allow(unused)] fn main() { pub trait IntoFuture { type Output; type IntoFuture: Future<Output = Self::Output>; // Обязательный метод fn into_future(self) -> Self::IntoFuture; } }
Преобразование в Future.
Реализуя IntoFuture для типа, вы определяете, как он будет преобразован в фьючер.
Десугаризация .await
Ключевое слово .await десугаризуется в вызов IntoFuture::into_future перед опросом фьючера до завершения. IntoFuture реализован для всех T: Future, что означает, что метод into_future будет доступен для всех фьючеров.
#![allow(unused)] fn main() { use std::future::IntoFuture; let v = async { "meow" }; let mut fut = v.into_future(); assert_eq!("meow", fut.await); }
Асинхронные билдеры
При ручной реализации фьючеров часто возникает выбор между реализацией Future или IntoFuture для типа. Реализация Future является хорошим выбором в большинстве случаев. Но реализация IntoFuture наиболее полезна при реализации типов "асинхронных билдеров", которые позволяют изменять свои значения несколько раз перед использованием .await.
use std::future::{ready, Ready, IntoFuture}; /// Умножает два числа в конечном счете pub struct Multiply { num: u16, factor: u16, } impl Multiply { /// Создает новый экземпляр `Multiply`. pub fn new(num: u16, factor: u16) -> Self { Self { num, factor } } /// Устанавливает число для умножения на множитель. pub fn number(mut self, num: u16) -> Self { self.num = num; self } /// Устанавливает множитель для умножения числа. pub fn factor(mut self, factor: u16) -> Self { self.factor = factor; self } } impl IntoFuture for Multiply { type Output = u16; type IntoFuture = Ready<Self::Output>; fn into_future(self) -> Self::IntoFuture { ready(self.num * self.factor) } } // ПРИМЕЧАНИЕ: Rust пока не имеет функции `async fn main`, эта функциональность // в настоящее время существует только в экосистеме. async fn run() { let num = Multiply::new(0, 0) // инициализирует билдер с number: 0, factor: 0 .number(2) // изменяет число на 2 .factor(2) // изменяет множитель на 2 .await; // преобразует в фьючер и ожидает assert_eq!(num, 4); }
Использование в границах трейтов
Использование IntoFuture в границах трейтов позволяет функции быть обобщенной как для Future, так и для IntoFuture. Это удобно для пользователей функции, так как при использовании им не нужно делать дополнительный вызов IntoFuture::into_future для получения экземпляра Future:
#![allow(unused)] fn main() { use std::future::IntoFuture; /// Преобразует вывод фьючера в строку. async fn fut_to_string<Fut>(fut: Fut) -> String where Fut: IntoFuture, Fut::Output: std::fmt::Debug, { format!("{:?}", fut.await) } }
Обязательные ассоциированные типы
type Output
Результат, который фьючер произведет при завершении.
type IntoFuture: Future<Output = Self::Output>
В какой тип фьючера мы преобразуем это значение?
Обязательные методы
fn into_future(self) -> Self::IntoFuture
Создает фьючер из значения.
Примеры
Базовое использование:
#![allow(unused)] fn main() { use std::future::IntoFuture; let v = async { "meow" }; let mut fut = v.into_future(); assert_eq!("meow", fut.await); }
Реализаторы
#![allow(unused)] fn main() { impl<F> IntoFuture for F where F: Future, }
Трейт AsyncDrop
#![allow(unused)] fn main() { pub trait AsyncDrop { // Обязательный метод async fn drop(self: Pin<&mut Self>); } }
🔬 Это экспериментальный API, доступный только в ночных сборках. (
async_drop#126482)
Асинхронная версия трейта Drop.
Когда значение больше не нужно, Rust запускает "деструктор" для этого значения. Наиболее распространенный случай, когда значение больше не нужно - это выход из области видимости. Деструкторы могут также запускаться в других обстоятельствах, но в примерах мы сосредоточимся на области видимости. Чтобы узнать о некоторых других случаях, пожалуйста, обратитесь к разделу справочника о деструкторах.
Copy и (Drop|AsyncDrop) являются взаимоисключающими
Вы не можете реализовать одновременно Copy и (Drop|AsyncDrop) для одного и того же типа. Типы, которые являются Copy, неявно дублируются компилятором, что делает очень трудным предсказание того, когда и как часто будут выполняться деструкторы. Как следствие, эти типы не могут иметь деструкторов.
Обязательные методы
#![allow(unused)] fn main() { async fn drop(self: Pin<&mut Self>) }
🔬 Это экспериментальный API, доступный только в ночных сборках. (
async_drop#126482)
Выполняет асинхронный деструктор для этого типа.
Этот метод вызывается неявно, когда значение выходит из области видимости, и не может быть вызван явно.
Когда этот метод вызывается, self еще не был деаллоцирован. Это происходит только после завершения метода.
Совместимость с dyn
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью", поэтому этот трейт не является объектно-безопасным.
Function
Function pending
#![allow(unused)] fn main() { pub fn pending<T>() -> Pending<T> ⓘ }
Создает фьючер, который никогда не разрешается, представляя вычисление, которое никогда не завершается.
Пример
#![allow(unused)] fn main() { use std::future; let future = future::pending(); let () = future.await; unreachable!(); }
Функция poll_fn
#![allow(unused)] fn main() { pub fn poll_fn<T, F>(f: F) -> PollFn<F> ⓘ where F: FnMut(&mut Context<'_>) -> Poll<T>, }
Создает фьючер, который оборачивает функцию, возвращающую
Poll.
Опрос фьючера делегируется обернутой функции. Если возвращенный фьючер закреплен (pinned), то захваченное окружение обернутой функции также закрепляется на месте, поэтому до тех пор, пока замыкание не перемещает свои захваты, оно может безопасно создавать закрепленные ссылки на них.
Примеры
#![allow(unused)] fn main() { use core::future::poll_fn; use std::task::{Context, Poll}; fn read_line(_cx: &mut Context<'_>) -> Poll<String> { Poll::Ready("Hello, World!".into()) } let read_future = poll_fn(read_line); assert_eq!(read_future.await, "Hello, World!".to_owned()); }
Захват закрепленного состояния
Пример замыкания, оборачивающего внутренние фьючеры:
#![allow(unused)] fn main() { use core::future::{self, Future}; use core::task::Poll; /// Разрешается в первый завершившийся фьючер. В случае ничьей побеждает `a`. fn naive_select<T>( a: impl Future<Output = T>, b: impl Future<Output = T>, ) -> impl Future<Output = T> { let (mut a, mut b) = (Box::pin(a), Box::pin(b)); future::poll_fn(move |cx| { if let Poll::Ready(r) = a.as_mut().poll(cx) { Poll::Ready(r) } else if let Poll::Ready(r) = b.as_mut().poll(cx) { Poll::Ready(r) } else { Poll::Pending } }) } let a = async { 42 }; let b = future::pending(); let v = naive_select(a, b).await; assert_eq!(v, 42); let a = future::pending(); let b = async { 27 }; let v = naive_select(a, b).await; assert_eq!(v, 27); let a = async { 42 }; let b = async { 27 }; let v = naive_select(a, b).await; assert_eq!(v, 42); // предвзятость к `a` в случае ничьей! }
На этот раз без Box::pin:
#![allow(unused)] fn main() { use core::future::{self, Future}; use core::pin::pin; use core::task::Poll; /// Разрешается в первый завершившийся фьючер. В случае ничьей побеждает `a`. fn naive_select<T>( a: impl Future<Output = T>, b: impl Future<Output = T>, ) -> impl Future<Output = T> { async { let (mut a, mut b) = (pin!(a), pin!(b)); future::poll_fn(move |cx| { if let Poll::Ready(r) = a.as_mut().poll(cx) { Poll::Ready(r) } else if let Poll::Ready(r) = b.as_mut().poll(cx) { Poll::Ready(r) } else { Poll::Pending } }).await } } let a = async { 42 }; let b = future::pending(); let v = naive_select(a, b).await; assert_eq!(v, 42); }
Обратите внимание, как благодаря нахождению в асинхронном контексте мы смогли заставить работать макрос
pin!, тем самым избежав необходимости использования небезопасного конструктораPin::new_unchecked(&mut fut).
Функция ready
#![allow(unused)] fn main() { pub fn ready<T>(t: T) -> Ready<T> ⓘ }
Создает фьючер, который немедленно готов со значением.
Фьючеры, созданные через эту функцию, функционально похожи на созданные через async {}. Основное различие в том, что фьючеры, созданные через эту функцию, имеют имя и реализуют Unpin.
Примеры
#![allow(unused)] fn main() { use std::future; let a = future::ready(1); assert_eq!(a.await, 1); }
Function async_drop_in_place
#![allow(unused)] fn main() { pub async unsafe fn async_drop_in_place<T>(_to_drop: *mut T) where T: ?Sized, }
🔬 Это экспериментальная функция ночной сборки API. (async_drop #126482)
Async drop.
Function async_drop_in_place
🔬 Экспериментальная (async_drop #126482)
#![allow(unused)] fn main() { pub async unsafe fn async_drop_in_place<T>(_to_drop: *mut T) where T: ?Sized, }
Модуль std::net
Сетевая функциональность для TCP/UDP-связи.
Этот модуль предоставляет сетевую функциональность для протоколов Transmission Control Protocol (TCP) и User Datagram Protocol (UDP).
Это руководство разделено на три основных раздела:
- TCP - тип
TcpListenerиTcpStream - UDP - тип
UdpSocket - Универсальные рассмотрения - адресация и преобразование имен
TCP
TCP - это надежный протокол потоковой передачи по протоколу Интернет (IP). Подключение TCP устанавливается с помощью трёхстороннего рукопожатия, которое обеспечивает надежное соединение между двумя узлами.
Использование TCP осуществляется двумя способами:
- либо путем прослушивания входящих подключений с помощью
TcpListener - либо путем подключения к удаленному узлу с помощью
TcpStream
Создание TCP-сервера с привязкой к адресу 127.0.0.1:8080:
use std::net::{TcpListener, TcpStream}; fn handle_client(stream: TcpStream) { // обработка подключения } fn main() -> std::io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; // принимаем входящие подключения и обрабатываем их for stream in listener.incoming() { handle_client(stream?); } Ok(()) }
Подключение к удаленному серверу по адресу 127.0.0.1:8080:
use std::net::TcpStream; fn main() -> std::io::Result<()> { let stream = TcpStream::connect("127.0.0.1:8080")?; // используем stream... Ok(()) }
UDP
UDP - это ненадежный протокол дейтаграмм по протоколу Интернет (IP). UDP-сообщения (пакеты) отправляются без установления предварительного соединения.
Использование UDP осуществляется с помощью UdpSocket:
use std::net::UdpSocket; fn main() -> std::io::Result<()> { { let socket = UdpSocket::bind("127.0.0.1:34254")?; // читаем из сокета let mut buf = [0; 1024]; let (amt, src) = socket.recv_from(&mut buf)?; // отправляем ответ let buf = &mut buf[..amt]; buf.reverse(); socket.send_to(buf, &src)?; } // сокет закрывается здесь Ok(()) }
Адресация и преобразование имен
Модуль std::net предоставляет механизмы для преобразования между объектами SocketAddr и строками, представляющими адреса или имена хостов.
Функция ToSocketAddrs предоставляет способ преобразования строк в SocketAddr, который является обобщенным для всех методов, которым нужна привязка или подключение к адресу.
Некоторые примеры допустимых форм адресов:
"localhost:1234""127.0.0.1:8080""127.0.0.1"(если указан порт по умолчанию)"[::1]:443""example.org:8080""example.org"(если указан порт по умолчанию)
Порт по умолчанию зависит от контекста. Например, для TcpStream::connect порт по умолчанию - 80, для TcpListener::bind - 0.
Функция ToSocketAddrs также реализована для SocketAddr и (IpAddr, u16), что позволяет явно передавать эти типы во все методы, принимающие ToSocketAddrs.
Преобразование имен хостов в адреса может блокировать текущий поток. Для асинхронного разрешения имен используйте крейт tokio или async-std (сейчас актуально библиотека smol).
Структуры
AddrParseError- ошибка, которая может быть возвращена при анализе адреса IP или сокетаIncoming- итератор, который бесконечноacceptподключения наTcpListenerIntoIncoming- итератор, который бесконечно принимает соединения наTcpListener. Эта структура создается методомTcpListener::into_incoming.Ipv4Addr- адрес IPv4Ipv6Addr- адрес IPv6SocketAddrV4- адрес интернет-сокета IPv4SocketAddrV6- адрес интернет-сокета IPv6TcpListener- структура, представляющая TCP-сервер, прослушивающий подключенияTcpStream- TCP-поток между локальным и удаленным сокетомUdpSocket- UDP-сокет
Перечисления
IpAddr- адрес IP, версия 4 или версия 6Shutdown- флаги для отключения частей соединенияSocketAddr- адрес интернет-сокета, IPv4 или IPv6Ipv6MulticastScope- область многоадресной рассылки IPv6
Типажи
ToSocketAddrs- типаж для объектов, которые могут быть преобразованы вSocketAddr
Рекомендации по использованию
Рассматриваются некоторые аспекты использования модуля net на практике
Сравнение TcpListener, TcpStream и UdpSocket
Когда что использовать
TcpListener
Используйте для создания TCP-серверов:
- Веб-серверы
- Серверы баз данных
- Игровые серверы
- Серверы реального времени
- API-серверы
use std::net::{TcpListener, TcpStream}; use std::thread; fn handle_client(stream: TcpStream) { // Обработка клиентского подключения } fn main() -> std::io::Result<()> { let listener = TcpListener::bind("0.0.0.0:8080")?; for stream in listener.incoming() { match stream { Ok(stream) => { thread::spawn(|| { handle_client(stream); }); } Err(e) => eprintln!("Ошибка подключения: {}", e), } } Ok(()) }
TcpStream
Используйте для TCP-клиентов и надежных соединений:
- Клиенты к серверам
- Передача файлов
- Веб-браузеры
- SSH/RDP клиенты
- Базы данных клиенты
use std::net::TcpStream; use std::io::{Read, Write}; fn main() -> std::io::Result<()> { let mut stream = TcpStream::connect("example.com:80")?; // Отправка HTTP запроса stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")?; // Чтение ответа let mut response = String::new(); stream.read_to_string(&mut response)?; println!("Ответ: {}", response); Ok(()) }
UdpSocket
Используйте для ненадежной, но быстрой передачи:
- VoIP (голосовая связь)
- Видеостриминг
- DNS запросы
- Игровая синхронизация
- Мониторинг и метрики
use std::net::UdpSocket; fn main() -> std::io::Result<()> { let socket = UdpSocket::bind("0.0.0.0:0")?; // Отправка дейтаграммы socket.send_to(b"Hello UDP!", "example.com:8080")?; // Получение ответа let mut buf = [0; 1024]; let (amt, src) = socket.recv_from(&mut buf)?; println!("Получено {} байт от {}", amt, src); Ok(()) }
Организация устойчивых TCP-соединений
1. Обработка ошибок и повторное подключение
#![allow(unused)] fn main() { use std::net::TcpStream; use std::io::{Read, Write}; use std::time::Duration; use std::thread; fn create_connection() -> Result<TcpStream, std::io::Error> { let mut attempts = 0; let max_attempts = 5; while attempts < max_attempts { match TcpStream::connect("127.0.0.1:8080") { Ok(stream) => { // Настройка параметров для надежности stream.set_read_timeout(Some(Duration::from_secs(30)))?; stream.set_write_timeout(Some(Duration::from_secs(30)))?; stream.set_nodelay(true)?; // Отключение Nagle для низкой задержки return Ok(stream); } Err(e) => { attempts += 1; eprintln!("Попытка {} не удалась: {}", attempts, e); thread::sleep(Duration::from_secs(2 * attempts as u64)); // Экспоненциальная задержка } } } Err(std::io::Error::new(std::io::ErrorKind::ConnectionRefused, "Не удалось подключиться после нескольких попыток")) } }
2. Сервер с пулом потоков
use std::net::{TcpListener, TcpStream}; use std::io::{Read, Write}; use std::sync::{Arc, Mutex}; use std::collections::VecDeque; use std::thread; struct ThreadPool { workers: Vec<Worker>, sender: std::sync::mpsc::Sender<Job>, } type Job = Box<dyn FnOnce() + Send + 'static>; impl ThreadPool { fn new(size: usize) -> ThreadPool { let (sender, receiver) = std::sync::mpsc::channel(); let receiver = Arc::new(Mutex::new(receiver)); let mut workers = Vec::with_capacity(size); for id in 0..size { workers.push(Worker::new(id, Arc::clone(&receiver))); } ThreadPool { workers, sender } } fn execute<F>(&self, f: F) where F: FnOnce() + Send + 'static, { let job = Box::new(f); self.sender.send(job).unwrap(); } } struct Worker { id: usize, thread: thread::JoinHandle<()>, } impl Worker { fn new(id: usize, receiver: Arc<Mutex<std::sync::mpsc::Receiver<Job>>>) -> Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); job(); }); Worker { id, thread } } } fn handle_client(mut stream: TcpStream) { let mut buffer = [0; 1024]; loop { match stream.read(&mut buffer) { Ok(0) => { // Соединение закрыто println!("Клиент отключился"); break; } Ok(n) => { // Эхо-ответ if let Err(e) = stream.write_all(&buffer[0..n]) { eprintln!("Ошибка записи: {}", e); break; } } Err(e) => { eprintln!("Ошибка чтения: {}", e); break; } } } } fn main() -> std::io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; let pool = ThreadPool::new(4); println!("Сервер запущен на 127.0.0.1:8080"); for stream in listener.incoming() { match stream { Ok(stream) => { pool.execute(|| { handle_client(stream); }); } Err(e) => eprintln!("Ошибка подключения: {}", e), } } Ok(()) }
3. Протокол с подтверждениями для UDP
#![allow(unused)] fn main() { use std::net::UdpSocket; use std::time::{Duration, Instant}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::thread; #[derive(Debug)] struct ReliableMessage { sequence: u32, data: Vec<u8>, timestamp: Instant, retries: u32, } struct ReliableUdpClient { socket: UdpSocket, sequence: u32, pending_acks: Arc<Mutex<HashMap<u32, ReliableMessage>>>, } impl ReliableUdpClient { fn new(bind_addr: &str) -> Result<Self, std::io::Error> { let socket = UdpSocket::bind(bind_addr)?; socket.set_read_timeout(Some(Duration::from_millis(100)))?; Ok(ReliableUdpClient { socket, sequence: 0, pending_acks: Arc::new(Mutex::new(HashMap::new())), }) } fn send_reliable(&mut self, data: &[u8], dest: &str) -> Result<(), std::io::Error> { let sequence = self.sequence; self.sequence += 1; // Добавляем номер последовательности к данным let mut packet = sequence.to_be_bytes().to_vec(); packet.extend_from_slice(data); // Сохраняем сообщение для повторной отправки let message = ReliableMessage { sequence, data: data.to_vec(), timestamp: Instant::now(), retries: 0, }; { let mut pending = self.pending_acks.lock().unwrap(); pending.insert(sequence, message); } // Отправка self.socket.send_to(&packet, dest)?; Ok(()) } fn start_ack_handler(&self) { let socket = self.socket.try_clone().unwrap(); let pending_acks = Arc::clone(&self.pending_acks); thread::spawn(move || { let mut buf = [0; 1024]; loop { match socket.recv_from(&mut buf) { Ok((amt, src)) => { if amt >= 4 { let sequence = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]); // Отправляем подтверждение let ack_packet = sequence.to_be_bytes(); let _ = socket.send_to(&ack_packet, src); // Удаляем из ожидающих подтверждения let mut pending = pending_acks.lock().unwrap(); pending.remove(&sequence); } } Err(_) => { // Таймаут - нормальная ситуация } } } }); } fn start_retry_handler(&self) { let socket = self.socket.try_clone().unwrap(); let pending_acks = Arc::clone(&self.pending_acks); thread::spawn(move || { loop { thread::sleep(Duration::from_millis(100)); let now = Instant::now(); let mut to_retry = Vec::new(); // Находим сообщения для повторной отправки { let mut pending = pending_acks.lock().unwrap(); for (seq, message) in pending.iter_mut() { if now.duration_since(message.timestamp) > Duration::from_secs(1) { if message.retries < 3 { message.retries += 1; message.timestamp = now; to_retry.push((*seq, message.data.clone())); } else { // Слишком много попыток - удаляем to_retry.push((*seq, Vec::new())); // Помечаем для удаления } } } // Удаляем сообщения с превышением лимита попыток for (seq, _) in to_retry.iter().filter(|(_, data)| data.is_empty()) { pending.remove(seq); } } // Повторно отправляем сообщения for (seq, data) in to_retry.into_iter().filter(|(_, data)| !data.is_empty()) { let mut packet = seq.to_be_bytes().to_vec(); packet.extend_from_slice(&data); let _ = socket.send_to(&packet, "127.0.0.1:8080"); } } }); } } }
Лучшие практики для надежных соединений
Для TCP:
- Таймауты - устанавливайте разумные таймауты чтения/записи
- Keep-alive - используйте TCP keep-alive для обнаружения разорванных соединений
- Обработка ошибок - всегда обрабатывайте возможные ошибки ввода-вывода
- Буферизация - используйте буферизированное чтение/запись
- Пул соединений - для серверов используйте пул потоков
Для UDP:
- Нумерация пакетов - добавляйте последовательные номера к пакетам
- Подтверждения - реализуйте механизм подтверждения получения
- Повторная отправка - реализуйте повторную отправку неподтвержденных пакетов
- Дубликаты - обрабатывайте возможные дубликаты пакетов
- Таймауты - устанавливайте таймауты для ожидания подтверждений
Универсальные рекомендации:
- Экспоненциальная задержка - при повторных попытках увеличивайте задержку
- Логирование - ведите логи важных событий и ошибок
- Мониторинг - отслеживайте количество активных соединений и ошибок
- Грейсфул shutdown - корректно закрывайте соединения при завершении
- Ограничение ресурсов - устанавливайте лимиты на количество одновременных соединений
Выбор между TCP и UDP зависит от требований приложения: TCP для надежности, UDP для скорости и низкой задержки.
Структуры
Структура AddrParseError
#![allow(unused)] fn main() { pub struct AddrParseError(_); }
Ошибка, которая может быть возвращена при анализе адреса IP или сокета.
Эта ошибка используется как ошибка типа для FromStr реализаций различных типов адресов в этом модуле, таких как IpAddr, SocketAddr, Ipv4Addr и других.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let invalid_str = "not-an-ip-address"; let err = IpAddr::from_str(invalid_str).unwrap_err(); println!("Ошибка анализа: {}", err); }
Методы
source
#![allow(unused)] fn main() { pub fn source(&self) -> Option<&(dyn Error + 'static)> }
Возвращает исходную ошибку, если таковая имеется.
Этот метод предоставляет доступ к исходной ошибке, которая привела к созданию этой ошибки анализа.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let invalid_str = "256.256.256.256"; // Неверный IP-адрес let err = IpAddr::from_str(invalid_str).unwrap_err(); if let Some(source) = err.source() { println!("Исходная ошибка: {}", source); } }
Трайт-реализации
Display
#![allow(unused)] fn main() { impl Display for AddrParseError }
Реализует отображение для AddrParseError.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let invalid_str = "not-an-ip"; let err = IpAddr::from_str(invalid_str).unwrap_err(); println!("Ошибка: {}", err); // Выводит читаемое сообщение об ошибке }
Debug
#![allow(unused)] fn main() { impl Debug for AddrParseError }
Реализует отладочное отображение для AddrParseError.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let invalid_str = "300.400.500.600"; let err = IpAddr::from_str(invalid_str).unwrap_err(); println!("Отладочная информация: {:?}", err); }
Error
#![allow(unused)] fn main() { impl Error for AddrParseError }
Реализует трейт Error для AddrParseError.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; use std::error::Error; let invalid_str = "invalid-ip-address"; let err = IpAddr::from_str(invalid_str).unwrap_err(); // Использование методов из трейта Error println!("Описание: {}", err); if let Some(source) = err.source() { println!("Источник: {}", source); } }
Clone, Copy
#![allow(unused)] fn main() { impl Clone for AddrParseError impl Copy for AddrParseError }
Реализует клонирование и копирование для AddrParseError.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let invalid_str = "999.999.999.999"; let err = IpAddr::from_str(invalid_str).unwrap_err(); let err_clone = err.clone(); // Клонирование ошибки println!("Оригинальная ошибка: {}", err); println!("Клонированная ошибка: {}", err_clone); }
Eq, PartialEq
#![allow(unused)] fn main() { impl Eq for AddrParseError impl PartialEq for AddrParseError }
Реализует сравнение для AddrParseError.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let err1 = IpAddr::from_str("invalid1").unwrap_err(); let err2 = IpAddr::from_str("invalid2").unwrap_err(); // Ошибки анализа считаются равными, независимо от входной строки assert_eq!(err1, err2); }
Примеры использования
Базовое использование с обработкой ошибок
use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; fn parse_ip_address(ip_str: &str) -> Result<IpAddr, String> { IpAddr::from_str(ip_str) .map_err(|e| format!("Неверный IP-адрес '{}': {}", ip_str, e)) } fn parse_socket_address(addr_str: &str) -> Result<SocketAddr, String> { SocketAddr::from_str(addr_str) .map_err(|e| format!("Неверный адрес сокета '{}': {}", addr_str, e)) } fn main() { // Тестирование валидных адресов let valid_ips = ["127.0.0.1", "::1", "192.168.1.1"]; for ip_str in &valid_ips { match parse_ip_address(ip_str) { Ok(ip) => println!("Успешно разобран IP: {}", ip), Err(e) => println!("Ошибка: {}", e), } } // Тестирование невалидных адресов let invalid_ips = ["256.256.256.256", "not_an_ip", "123.456.789.000"]; for ip_str in &invalid_ips { match parse_ip_address(ip_str) { Ok(ip) => println!("Успешно разобран IP: {}", ip), Err(e) => println!("Ошибка: {}", e), } } // Тестирование адресов сокетов let socket_str = "127.0.0.1:8080"; match parse_socket_address(socket_str) { Ok(addr) => println!("Успешно разобран адрес сокета: {}", addr), Err(e) => println!("Ошибка: {}", e), } }
Создание пользовательских парсеров с детальной обработкой ошибок
use std::net::{IpAddr, AddrParseError}; use std::str::FromStr; use std::error::Error; #[derive(Debug)] struct NetworkConfig { ip: IpAddr, port: u16, } impl NetworkConfig { fn from_str(s: &str) -> Result<Self, Box<dyn Error>> { let parts: Vec<&str> = s.split(':').collect(); if parts.len() != 2 { return Err("Ожидается формат 'IP:PORT'".into()); } let ip = IpAddr::from_str(parts[0]) .map_err(|e: AddrParseError| { format!("Неверный IP-адрес '{}': {}", parts[0], e) })?; let port = parts[1].parse::<u16>() .map_err(|e| { format!("Неверный порт '{}': {}", parts[1], e) })?; Ok(NetworkConfig { ip, port }) } } fn main() { let test_cases = [ "127.0.0.1:8080", "::1:9000", "invalid_ip:8080", "192.168.1.1:99999", // Неверный порт "no_colon", // Отсутствует разделитель ]; for test_case in &test_cases { println!("Разбор '{}':", test_case); match NetworkConfig::from_str(test_case) { Ok(config) => println!(" Успех: IP={}, PORT={}", config.ip, config.port), Err(e) => println!(" Ошибка: {}", e), } println!(); } }
Валидация пользовательского ввода
use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; fn validate_user_input(input: &str) -> Result<(), String> { // Попробуем разобрать как IP-адрес if let Ok(ip) = IpAddr::from_str(input) { if ip.is_loopback() { return Err("IP-адрес обратной петли не разрешен".to_string()); } if ip.is_unspecified() { return Err("Неспецифицированный IP-адрес не разрешен".to_string()); } println!("Валидный IP-адрес: {}", ip); return Ok(()); } // Попробуем разобрать как адрес сокета if let Ok(socket) = SocketAddr::from_str(input) { if socket.port() == 0 { return Err("Порт 0 не разрешен".to_string()); } println!("Валидный адрес сокета: {}", socket); return Ok(()); } Err(format!("'{}' не является валидным IP-адресом или адресом сокета", input)) } fn main() { let inputs = [ "127.0.0.1", "192.168.1.1", "0.0.0.0", "google.com:80", "256.256.256.256", "localhost:8080", "123.45.67.89:0", ]; for input in &inputs { println!("Валидация '{}':", input); match validate_user_input(input) { Ok(()) => println!(" ✓ Валидный ввод"), Err(e) => println!(" ✗ Ошибка: {}", e), } } }
Интеграция с другими типами ошибок
use std::net::{IpAddr, AddrParseError}; use std::str::FromStr; use thiserror::Error; #[derive(Error, Debug)] pub enum ConfigError { #[error("Ошибка анализа IP-адреса '{input}': {source}")] AddrParse { input: String, source: AddrParseError, }, #[error("Ошибка ввода-вывода: {0}")] Io(#[from] std::io::Error), #[error("Неверный формат конфигурации: {0}")] InvalidFormat(String), } pub fn parse_ip_with_detailed_error(ip_str: &str) -> Result<IpAddr, ConfigError> { IpAddr::from_str(ip_str) .map_err(|source| ConfigError::AddrParse { input: ip_str.to_string(), source, }) } pub fn load_config_from_file(filename: &str, ip_str: &str) -> Result<(), ConfigError> { // Имитация чтения файла println!("Чтение конфигурации из {}", filename); // Разбор IP-адреса с детализированной ошибкой let ip = parse_ip_with_detailed_error(ip_str)?; println!("Загружена конфигурация с IP: {}", ip); Ok(()) } fn main() { let test_cases = [ ("config1.txt", "192.168.1.1"), ("config2.txt", "invalid_ip"), ("config3.txt", "999.999.999.999"), ]; for (filename, ip_str) in &test_cases { println!("Обработка {} с IP {}", filename, ip_str); match load_config_from_file(filename, ip_str) { Ok(()) => println!(" ✓ Успех"), Err(e) => println!(" ✗ Ошибка: {}", e), } println!(); } }
Утилитарные функции для работы с ошибками анализа
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, AddrParseError}; use std::str::FromStr; fn analyze_parse_error(input: &str) { println!("Анализ ошибки для '{}':", input); // Проверяем различные типы адресов match IpAddr::from_str(input) { Ok(ip) => println!(" ✓ Валидный IP-адрес: {}", ip), Err(e) => { println!(" ✗ Ошибка анализа IP: {}", e); // Детальный анализ if let Ok(ipv4) = Ipv4Addr::from_str(input) { println!(" - Но это валидный IPv4: {}", ipv4); } else if let Ok(ipv6) = Ipv6Addr::from_str(input) { println!(" - Но это валидный IPv6: {}", ipv6); } else { println!(" - Не является валидным ни IPv4, ни IPv6"); } } } } fn suggest_correction(input: &str) -> Option<String> { // Простые эвристики для предложения исправлений let trimmed = input.trim(); // Убираем лишние пробелы if trimmed != input { return Some(trimmed.to_string()); } // Проверяем IPv6 без скобок if trimmed.contains(':') && !trimmed.starts_with('[') { let suggestion = format!("[{}]", trimmed); if IpAddr::from_str(&suggestion).is_ok() { return Some(suggestion); } } None } fn main() { let problematic_inputs = [ " 127.0.0.1 ", // Лишние пробелы "::1", // IPv6 без скобок для адреса сокета "192.168.001.001", // Ведущие нули "fe80::1%eth0", // IPv6 с зоной ]; for input in &problematic_inputs { analyze_parse_error(input); if let Some(suggestion) = suggest_correction(input) { println!(" 💡 Предложение: попробуйте '{}'", suggestion); if IpAddr::from_str(&suggestion).is_ok() { println!(" ✅ Предложение работает!"); } } println!(); } }
Распространенные сценарии ошибок
Неверные IPv4 адреса
"256.256.256.256"- октеты больше 255"192.168.1"- недостаточно октетов"192.168.1.1.1"- слишком много октетов"192.168.1."- незавершенный адрес
Неверные IPv6 адреса
"::fffff"- неверный формат"2001:db8::1::1"- множественные::"2001:db8:xyz::1"- неверные шестнадцатеричные цифры
Неверные адреса сокетов
"127.0.0.1:"- отсутствует порт"127.0.0.1:99999"- порт вне диапазона"[::1]"- IPv6 без порта
Структура Ipv4Addr
#![allow(unused)] fn main() { pub struct Ipv4Addr(_); }
Адрес IPv4.
IPv4-адреса определяются как 32-битные целые числа в IETF RFC 791. Они обычно представляются в точечно-десятичной нотации, которая состоит из четырех октетов, разделенных точками.
См. также IpAddr для типа, представляющий либо IPv4, либо IPv6.
Представление в памяти
Ipv4Addr представляет собой 32-битное целое число без знака, хранящееся в сетевом порядке байт (big-endian). Это то же представление, что и в системных вызовах Unix и Windows.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let localhost = Ipv4Addr::new(127, 0, 0, 1); assert_eq!("127.0.0.1".parse(), Ok(localhost)); let broadcast = Ipv4Addr::new(255, 255, 255, 255); assert_eq!(broadcast, Ipv4Addr::BROADCAST); }
Константы
UNSPECIFIED
#![allow(unused)] fn main() { pub const UNSPECIFIED: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0); }
Неспецифицированный адрес IPv4: 0.0.0.0.
Это соответствует константе INADDR_ANY в системных вызовах.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::UNSPECIFIED; assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); assert!(addr.is_unspecified()); }
LOCALHOST
#![allow(unused)] fn main() { pub const LOCALHOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); }
Адрес обратной петли IPv4: 127.0.0.1.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::LOCALHOST; assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); assert!(addr.is_loopback()); }
BROADCAST
#![allow(unused)] fn main() { pub const BROADCAST: Ipv4Addr = Ipv4Addr::new(255, 255, 255, 255); }
Широковещательный адрес IPv4: 255.255.255.255.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::BROADCAST; assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); assert!(addr.is_broadcast()); }
Методы
new
#![allow(unused)] fn main() { pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr }
Создает новый IPv4-адрес из четырех восьмибитных октетов.
Результат представляет собой адрес a.b.c.d.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(127, 0, 0, 1); assert_eq!(addr.to_string(), "127.0.0.1"); }
octets
#![allow(unused)] fn main() { pub const fn octets(&self) -> [u8; 4] }
Возвращает четыре восьмибитных октета, из которых состоит адрес.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(127, 0, 0, 1); assert_eq!(addr.octets(), [127, 0, 0, 1]); }
is_unspecified
#![allow(unused)] fn main() { pub const fn is_unspecified(&self) -> bool }
Возвращает true, если это неспецифицированный адрес (0.0.0.0).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let unspecified = Ipv4Addr::new(0, 0, 0, 0); let localhost = Ipv4Addr::new(127, 0, 0, 1); assert!(unspecified.is_unspecified()); assert!(!localhost.is_unspecified()); }
is_loopback
#![allow(unused)] fn main() { pub const fn is_loopback(&self) -> bool }
Возвращает true, если это адрес обратной петли (127.0.0.0/8).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let localhost = Ipv4Addr::new(127, 0, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(localhost.is_loopback()); assert!(!other.is_loopback()); }
is_private
#![allow(unused)] fn main() { pub const fn is_private(&self) -> bool }
Возвращает true, если это частный адрес.
Частные адреса IPv4 определены в IETF RFC 1918:
10.0.0.0/8172.16.0.0/12192.168.0.0/16
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let private1 = Ipv4Addr::new(10, 0, 0, 1); let private2 = Ipv4Addr::new(172, 16, 0, 1); let private3 = Ipv4Addr::new(192, 168, 1, 1); let public = Ipv4Addr::new(8, 8, 8, 8); assert!(private1.is_private()); assert!(private2.is_private()); assert!(private3.is_private()); assert!(!public.is_private()); }
is_link_local
#![allow(unused)] fn main() { pub const fn is_link_local(&self) -> bool }
Возвращает true, если это link-local адрес (169.254.0.0/16).
Link-local адреса определены в IETF RFC 3927.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let link_local = Ipv4Addr::new(169, 254, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(link_local.is_link_local()); assert!(!other.is_link_local()); }
is_global
#![allow(unused)] fn main() { pub fn is_global(&self) -> bool }
Возвращает true, если это глобальный (публично маршрутизируемый) адрес.
Глобальные адреса - это все адреса, которые не зарезервированы для специальных целей.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let global = Ipv4Addr::new(8, 8, 8, 8); let private = Ipv4Addr::new(192, 168, 1, 1); assert!(global.is_global()); assert!(!private.is_global()); }
is_shared
#![allow(unused)] fn main() { pub fn is_shared(&self) -> bool }
Возвращает true, если это shared-адрес (100.64.0.0/10).
Shared-адреса определены в IETF RFC 6598.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let shared = Ipv4Addr::new(100, 64, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(shared.is_shared()); assert!(!other.is_shared()); }
is_benchmarking
#![allow(unused)] fn main() { pub fn is_benchmarking(&self) -> bool }
Возвращает true, если это benchmarking-адрес (198.18.0.0/15).
Benchmarking-адреса определены в IETF RFC 2544.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let benchmarking = Ipv4Addr::new(198, 18, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(benchmarking.is_benchmarking()); assert!(!other.is_benchmarking()); }
is_reserved
#![allow(unused)] fn main() { pub fn is_reserved(&self) -> bool }
Возвращает true, если это зарезервированный адрес (240.0.0.0/4).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let reserved = Ipv4Addr::new(240, 0, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(reserved.is_reserved()); assert!(!other.is_reserved()); }
is_multicast
#![allow(unused)] fn main() { pub const fn is_multicast(&self) -> bool }
Возвращает true, если это многоадресный адрес (224.0.0.0/4).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let multicast = Ipv4Addr::new(224, 0, 0, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(multicast.is_multicast()); assert!(!other.is_multicast()); }
is_broadcast
#![allow(unused)] fn main() { pub const fn is_broadcast(&self) -> bool }
Возвращает true, если это широковещательный адрес (255.255.255.255).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let broadcast = Ipv4Addr::new(255, 255, 255, 255); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(broadcast.is_broadcast()); assert!(!other.is_broadcast()); }
is_documentation
#![allow(unused)] fn main() { pub fn is_documentation(&self) -> bool }
Возвращает true, если это адрес, зарезервированный для документации.
Адреса документации определены в IETF RFC 5737:
192.0.2.0/24198.51.100.0/24203.0.113.0/24
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let doc1 = Ipv4Addr::new(192, 0, 2, 1); let doc2 = Ipv4Addr::new(198, 51, 100, 1); let doc3 = Ipv4Addr::new(203, 0, 113, 1); let other = Ipv4Addr::new(192, 168, 1, 1); assert!(doc1.is_documentation()); assert!(doc2.is_documentation()); assert!(doc3.is_documentation()); assert!(!other.is_documentation()); }
to_ipv6_compatible
#![allow(unused)] fn main() { pub const fn to_ipv6_compatible(&self) -> Ipv6Addr }
Преобразует адрес IPv4 в IPv4-совместимый адрес IPv6.
IPv4-совместимые адреса IPv6 устарели. Вместо них используйте to_ipv6_mapped.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, Ipv6Addr}; let ipv4 = Ipv4Addr::new(192, 0, 2, 1); let ipv6_compatible = ipv4.to_ipv6_compatible(); assert_eq!( ipv6_compatible, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x201) ); }
to_ipv6_mapped
#![allow(unused)] fn main() { pub const fn to_ipv6_mapped(&self) -> Ipv6Addr }
Преобразует адрес IPv4 в IPv4-отображенный адрес IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, Ipv6Addr}; let ipv4 = Ipv4Addr::new(192, 0, 2, 1); let ipv6_mapped = ipv4.to_ipv6_mapped(); assert_eq!( ipv6_mapped, Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x201) ); }
to_bits
#![allow(unused)] fn main() { pub const fn to_bits(&self) -> u32 }
Возвращает 32-битное представление адреса в порядке байт хоста.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(0x7f, 0, 0, 1); assert_eq!(addr.to_bits(), 0x7f000001); }
from_bits
#![allow(unused)] fn main() { pub const fn from_bits(bits: u32) -> Ipv4Addr }
Создает Ipv4Addr из 32-битного представления в порядке байт хоста.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::from_bits(0x7f000001); assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); }
Трайт-реализации
From<[u8; 4]>
#![allow(unused)] fn main() { impl From<[u8; 4]> for Ipv4Addr }
Преобразует [u8; 4] в Ipv4Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let bytes = [127, 0, 0, 1]; let addr = Ipv4Addr::from(bytes); assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); }
From<u32>
#![allow(unused)] fn main() { impl From<u32> for Ipv4Addr }
Преобразует u32 в Ipv4Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::from(0x7f000001); assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); }
Into<[u8; 4]>
#![allow(unused)] fn main() { impl Into<[u8; 4]> for Ipv4Addr }
Преобразует Ipv4Addr в [u8; 4].
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(127, 0, 0, 1); let bytes: [u8; 4] = addr.into(); assert_eq!(bytes, [127, 0, 0, 1]); }
Into<u32>
#![allow(unused)] fn main() { impl Into<u32> for Ipv4Addr }
Преобразует Ipv4Addr в u32.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(127, 0, 0, 1); let bits: u32 = addr.into(); assert_eq!(bits, 0x7f000001); }
Display, Debug
#![allow(unused)] fn main() { impl Display for Ipv4Addr impl Debug for Ipv4Addr }
Реализует отображение и отладочное отображение для Ipv4Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(192, 168, 1, 1); println!("IP адрес: {}", addr); // "192.168.1.1" println!("Отладочная информация: {:?}", addr); // "192.168.1.1" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for Ipv4Addr impl Eq for Ipv4Addr impl PartialOrd for Ipv4Addr impl Ord for Ipv4Addr impl Hash for Ipv4Addr }
Реализует сравнение и хеширование для Ipv4Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; use std::collections::HashMap; let addr1 = Ipv4Addr::new(192, 168, 1, 1); let addr2 = Ipv4Addr::new(192, 168, 1, 1); let addr3 = Ipv4Addr::new(10, 0, 0, 1); assert_eq!(addr1, addr2); assert_ne!(addr1, addr3); let mut map = HashMap::new(); map.insert(addr1, "router"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for Ipv4Addr }
Реализует парсинг из строки для Ipv4Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv4Addr; use std::str::FromStr; let addr = Ipv4Addr::from_str("192.168.1.1").unwrap(); assert_eq!(addr, Ipv4Addr::new(192, 168, 1, 1)); }
Примеры использования
Создание и проверка IPv4 адресов
use std::net::Ipv4Addr; fn analyze_ipv4(addr: Ipv4Addr) { println!("Анализ IPv4 адреса: {}", addr); println!(" Октеты: {:?}", addr.octets()); println!(" 32-битное значение: 0x{:08x}", addr.to_bits()); // Проверка свойств let properties = [ ("неспецифицированный", addr.is_unspecified()), ("обратная петля", addr.is_loopback()), ("частный", addr.is_private()), ("link-local", addr.is_link_local()), ("глобальный", addr.is_global()), ("shared", addr.is_shared()), ("benchmarking", addr.is_benchmarking()), ("зарезервированный", addr.is_reserved()), ("многоадресный", addr.is_multicast()), ("широковещательный", addr.is_broadcast()), ("для документации", addr.is_documentation()), ]; for (name, value) in properties { if value { println!(" ✓ {}", name); } } } fn main() { let addresses = [ Ipv4Addr::UNSPECIFIED, Ipv4Addr::LOCALHOST, Ipv4Addr::BROADCAST, Ipv4Addr::new(10, 0, 0, 1), Ipv4Addr::new(192, 168, 1, 1), Ipv4Addr::new(224, 0, 0, 1), Ipv4Addr::new(8, 8, 8, 8), ]; for addr in addresses { analyze_ipv4(addr); println!(); } }
Преобразование между форматами
use std::net::Ipv4Addr; fn demonstrate_conversions() { let original = Ipv4Addr::new(192, 168, 1, 1); // Преобразование в массив байт let bytes: [u8; 4] = original.octets(); println!("Оригинальный: {}", original); println!("Массив байт: {:?}", bytes); // Преобразование из массива байт let from_bytes = Ipv4Addr::from(bytes); println!("Из массива байт: {}", from_bytes); // Преобразование в u32 let bits = original.to_bits(); println!("32-битное значение: 0x{:08x}", bits); // Преобразование из u32 let from_bits = Ipv4Addr::from_bits(bits); println!("Из 32-битного: {}", from_bits); // IPv6 преобразования let ipv6_mapped = original.to_ipv6_mapped(); println!("IPv4-отображенный IPv6: {}", ipv6_mapped); let ipv6_compatible = original.to_ipv6_compatible(); println!("IPv4-совместимый IPv6: {}", ipv6_compatible); } fn main() { demonstrate_conversions(); }
Фильтрация IP-адресов
use std::net::Ipv4Addr; struct NetworkFilter; impl NetworkFilter { fn is_allowed(addr: Ipv4Addr) -> bool { // Запрещаем специальные адреса if addr.is_unspecified() || addr.is_loopback() { return false; } // Запрещаем частные адреса if addr.is_private() { return false; } // Запрещаем зарезервированные и специальные диапазоны if addr.is_link_local() || addr.is_shared() || addr.is_benchmarking() || addr.is_reserved() || addr.is_documentation() { return false; } // Разрешаем только глобальные адреса addr.is_global() } fn filter_addresses(addrs: Vec<Ipv4Addr>) -> Vec<Ipv4Addr> { addrs.into_iter() .filter(|&addr| Self::is_allowed(addr)) .collect() } } fn main() { let test_addresses = vec![ Ipv4Addr::UNSPECIFIED, Ipv4Addr::LOCALHOST, Ipv4Addr::new(10, 0, 0, 1), Ipv4Addr::new(192, 168, 1, 1), Ipv4Addr::new(169, 254, 0, 1), Ipv4Addr::new(8, 8, 8, 8), // Google DNS - разрешен Ipv4Addr::new(1, 1, 1, 1), // Cloudflare DNS - разрешен ]; println!("Все адреса:"); for addr in &test_addresses { println!(" {} - {}", addr, if NetworkFilter::is_allowed(*addr) { "✓" } else { "✗" }); } let filtered = NetworkFilter::filter_addresses(test_addresses); println!("\nРазрешенные адреса:"); for addr in filtered { println!(" {}", addr); } }
Структура Ipv6Addr
#![allow(unused)] fn main() { pub struct Ipv6Addr(_); }
Адрес IPv6.
IPv6-адреса определяются как 128-битные целые числа в IETF RFC 4291. Они обычно представляются в виде восьми 16-битных сегментов, разделенных двоеточиями.
См. также IpAddr для типа, представляющий либо IPv4, либо IPv6.
Представление в памяти
Ipv6Addr представляет собой 128-битное целое число без знака, хранящееся в сетевом порядке байт (big-endian). Это то же представление, что и в системных вызовах Unix и Windows.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); assert_eq!("::1".parse(), Ok(localhost)); let unspecified = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); assert_eq!(unspecified, Ipv6Addr::UNSPECIFIED); }
Константы
UNSPECIFIED
#![allow(unused)] fn main() { pub const UNSPECIFIED: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); }
Неспецифицированный адрес IPv6: ::.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::UNSPECIFIED; assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); assert!(addr.is_unspecified()); }
LOCALHOST
#![allow(unused)] fn main() { pub const LOCALHOST: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); }
Адрес обратной петли IPv6: ::1.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::LOCALHOST; assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); assert!(addr.is_loopback()); }
BROADCAST
#![allow(unused)] fn main() { // Примечание: IPv6 не имеет широковещательных адресов, используется многоадресная рассылка }
В IPv6 нет широковещательных адресов. Вместо них используется многоадресная рассылка.
Методы
new
#![allow(unused)] fn main() { pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr }
Создает новый IPv6-адрес из восьми 16-битных сегментов.
Результат представляет собой адрес a:b:c:d:e:f:g:h.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert_eq!(addr.to_string(), "2001:db8::1"); }
segments
#![allow(unused)] fn main() { pub const fn segments(&self) -> [u16; 8] }
Возвращает восемь 16-битных сегментов, из которых состоит адрес.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert_eq!(addr.segments(), [0x2001, 0xdb8, 0, 0, 0, 0, 0, 1]); }
is_unspecified
#![allow(unused)] fn main() { pub const fn is_unspecified(&self) -> bool }
Возвращает true, если это неспецифицированный адрес (::).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let unspecified = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); assert!(unspecified.is_unspecified()); assert!(!localhost.is_unspecified()); }
is_loopback
#![allow(unused)] fn main() { pub const fn is_loopback(&self) -> bool }
Возвращает true, если это адрес обратной петли (::1).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); let other = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert!(localhost.is_loopback()); assert!(!other.is_loopback()); }
is_global
#![allow(unused)] fn main() { pub fn is_global(&self) -> bool }
Возвращает true, если это глобальный (публично маршрутизируемый) адрес.
Глобальные адреса - это все адреса, которые не зарезервированы для специальных целей.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let global = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let unique_local = Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1); assert!(global.is_global()); assert!(!unique_local.is_global()); }
is_unique_local
#![allow(unused)] fn main() { pub fn is_unique_local(&self) -> bool }
Возвращает true, если это unique local адрес (fc00::/7).
Unique local адреса определены в IETF RFC 4193 и являются аналогом IPv4 частных адресов.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let unique_local = Ipv6Addr::new(0xfd00, 0, 0, 0, 0, 0, 0, 1); let global = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert!(unique_local.is_unique_local()); assert!(!global.is_unique_local()); }
is_unicast_link_local
#![allow(unused)] fn main() { pub const fn is_unicast_link_local(&self) -> bool }
Возвращает true, если это unicast link-local адрес (fe80::/10).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let link_local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); let global = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert!(link_local.is_unicast_link_local()); assert!(!global.is_unicast_link_local()); }
is_unicast_site_local
#![allow(unused)] fn main() { #[deprecated = "используйте Ipv6Addr::is_unique_local вместо этого"] pub fn is_unicast_site_local(&self) -> bool }
Устарело: используйте is_unique_local вместо этого.
is_documentation
#![allow(unused)] fn main() { pub fn is_documentation(&self) -> bool }
Возвращает true, если это адрес, зарезервированный для документации (2001:db8::/32).
Адреса документации определены в IETF RFC 3849.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let doc = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let other = Ipv6Addr::new(0x2001, 0xdb9, 0, 0, 0, 0, 0, 1); assert!(doc.is_documentation()); assert!(!other.is_documentation()); }
is_multicast
#![allow(unused)] fn main() { pub const fn is_multicast(&self) -> bool }
Возвращает true, если это многоадресный адрес (ff00::/8).
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let multicast = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1); let unicast = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert!(multicast.is_multicast()); assert!(!unicast.is_multicast()); }
multicast_scope
#![allow(unused)] fn main() { pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> }
Возвращает область многоадресной рассылки, если это многоадресный адрес.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, Ipv6MulticastScope}; let multicast = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1); if let Some(scope) = multicast.multicast_scope() { println!("Область многоадресной рассылки: {:?}", scope); } }
is_unicast_global
#![allow(unused)] fn main() { pub fn is_unicast_global(&self) -> bool }
Возвращает true, если это глобальный unicast адрес.
Глобальные unicast адреса определены в IETF RFC 4291 и включают большинство публично маршрутизируемых адресов.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let global_unicast = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let link_local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1); assert!(global_unicast.is_unicast_global()); assert!(!link_local.is_unicast_global()); }
to_ipv4
#![allow(unused)] fn main() { pub fn to_ipv4(&self) -> Option<Ipv4Addr> }
Преобразует IPv4-отображенный или IPv4-совместимый адрес IPv6 в IPv4.
Возвращает Some(Ipv4Addr), если адрес является IPv4-отображенным (::ffff:0:0/96) или IPv4-совместимым (::/96), иначе None.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, Ipv6Addr}; let ipv4_mapped = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x201); let ipv4 = ipv4_mapped.to_ipv4().unwrap(); assert_eq!(ipv4, Ipv4Addr::new(192, 0, 2, 1)); let regular_ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert!(regular_ipv6.to_ipv4().is_none()); }
to_ipv4_mapped
#![allow(unused)] fn main() { pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> }
Преобразует IPv4-отображенный адрес IPv6 в IPv4.
Возвращает Some(Ipv4Addr), если адрес является IPv4-отображенным (::ffff:0:0/96), иначе None.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, Ipv6Addr}; let ipv4_mapped = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x201); let ipv4 = ipv4_mapped.to_ipv4_mapped().unwrap(); assert_eq!(ipv4, Ipv4Addr::new(192, 0, 2, 1)); let ipv4_compatible = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x201); assert!(ipv4_compatible.to_ipv4_mapped().is_none()); }
to_bits
#![allow(unused)] fn main() { pub const fn to_bits(&self) -> u128 }
Возвращает 128-битное представление адреса в порядке байт хоста.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); assert_eq!(addr.to_bits(), 0x20010db8000000000000000000000001); }
from_bits
#![allow(unused)] fn main() { pub const fn from_bits(bits: u128) -> Ipv6Addr }
Создает Ipv6Addr из 128-битного представления в порядке байт хоста.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::from_bits(0x20010db8000000000000000000000001); assert_eq!(addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
octets
#![allow(unused)] fn main() { pub const fn octets(&self) -> [u8; 16] }
Возвращает шестнадцать восьмибитных октетов, из которых состоит адрес.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let octets = addr.octets(); assert_eq!(octets[0..2], [0x20, 0x01]); // 2001 assert_eq!(octets[2..4], [0x0d, 0xb8]); // db8 }
Трайт-реализации
From<[u16; 8]>
#![allow(unused)] fn main() { impl From<[u16; 8]> for Ipv6Addr }
Преобразует [u16; 8] в Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let segments = [0x2001, 0xdb8, 0, 0, 0, 0, 0, 1]; let addr = Ipv6Addr::from(segments); assert_eq!(addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
From<[u8; 16]>
#![allow(unused)] fn main() { impl From<[u8; 16]> for Ipv6Addr }
Преобразует [u8; 16] в Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let octets = [ 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]; let addr = Ipv6Addr::from(octets); assert_eq!(addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
From<u128>
#![allow(unused)] fn main() { impl From<u128> for Ipv6Addr }
Преобразует u128 в Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::from(0x20010db8000000000000000000000001); assert_eq!(addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
Into<[u16; 8]>
#![allow(unused)] fn main() { impl Into<[u16; 8]> for Ipv6Addr }
Преобразует Ipv6Addr в [u16; 8].
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let segments: [u16; 8] = addr.into(); assert_eq!(segments, [0x2001, 0xdb8, 0, 0, 0, 0, 0, 1]); }
Into<[u8; 16]>
#![allow(unused)] fn main() { impl Into<[u8; 16]> for Ipv6Addr }
Преобразует Ipv6Addr в [u8; 16].
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let octets: [u8; 16] = addr.into(); assert_eq!(octets[0..2], [0x20, 0x01]); }
Into<u128>
#![allow(unused)] fn main() { impl Into<u128> for Ipv6Addr }
Преобразует Ipv6Addr в u128.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let bits: u128 = addr.into(); assert_eq!(bits, 0x20010db8000000000000000000000001); }
Display, Debug
#![allow(unused)] fn main() { impl Display for Ipv6Addr impl Debug for Ipv6Addr }
Реализует отображение и отладочное отображение для Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; let addr = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); println!("IP адрес: {}", addr); // "2001:db8::1" println!("Отладочная информация: {:?}", addr); // "2001:db8::1" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for Ipv6Addr impl Eq for Ipv6Addr impl PartialOrd for Ipv6Addr impl Ord for Ipv6Addr impl Hash for Ipv6Addr }
Реализует сравнение и хеширование для Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; use std::collections::HashMap; let addr1 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let addr2 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); let addr3 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2); assert_eq!(addr1, addr2); assert_ne!(addr1, addr3); let mut map = HashMap::new(); map.insert(addr1, "server"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for Ipv6Addr }
Реализует парсинг из строки для Ipv6Addr.
Примеры
#![allow(unused)] fn main() { use std::net::Ipv6Addr; use std::str::FromStr; let addr = Ipv6Addr::from_str("2001:db8::1").unwrap(); assert_eq!(addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
Примеры использования
Создание и проверка IPv6 адресов
use std::net::Ipv6Addr; fn analyze_ipv6(addr: Ipv6Addr) { println!("Анализ IPv6 адреса: {}", addr); println!(" Сегменты: {:x?}", addr.segments()); println!(" 128-битное значение: 0x{:032x}", addr.to_bits()); // Проверка свойств let properties = [ ("неспецифицированный", addr.is_unspecified()), ("обратная петля", addr.is_loopback()), ("глобальный", addr.is_global()), ("unique local", addr.is_unique_local()), ("unicast link-local", addr.is_unicast_link_local()), ("для документации", addr.is_documentation()), ("многоадресный", addr.is_multicast()), ("unicast global", addr.is_unicast_global()), ]; for (name, value) in properties { if value { println!(" ✓ {}", name); } } // Проверка многоадресной области if let Some(scope) = addr.multicast_scope() { println!(" Область многоадресной рассылки: {:?}", scope); } // Попытка преобразования в IPv4 if let Some(ipv4) = addr.to_ipv4() { println!(" IPv4-отображенный: {}", ipv4); } } fn main() { let addresses = [ Ipv6Addr::UNSPECIFIED, Ipv6Addr::LOCALHOST, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), // Документация Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), // Link-local Ipv6Addr::new(0xfd00, 0, 0, 0, 0, 0, 0, 1), // Unique local Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1), // Multicast Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x201), // IPv4-mapped ]; for addr in addresses { analyze_ipv6(addr); println!(); } }
Преобразование между форматами
use std::net::{Ipv4Addr, Ipv6Addr}; fn demonstrate_ipv6_conversions() { let original = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1); // Преобразование в сегменты let segments = original.segments(); println!("Оригинальный: {}", original); println!("Сегменты: {:x?}", segments); // Преобразование из сегментов let from_segments = Ipv6Addr::from(segments); println!("Из сегментов: {}", from_segments); // Преобразование в u128 let bits = original.to_bits(); println!("128-битное значение: 0x{:032x}", bits); // Преобразование из u128 let from_bits = Ipv6Addr::from_bits(bits); println!("Из 128-битного: {}", from_bits); // Преобразование в октеты let octets = original.octets(); println!("Октеты: {:02x?}", octets); // Преобразование из октетов let from_octets = Ipv6Addr::from(octets); println!("Из октетов: {}", from_octets); // Работа с IPv4-отображенными адресами let ipv4 = Ipv4Addr::new(192, 168, 1, 1); let ipv6_mapped = ipv4.to_ipv6_mapped(); println!("IPv4: {}", ipv4); println!("IPv4-отображенный IPv6: {}", ipv6_mapped); if let Some(back_to_ipv4) = ipv6_mapped.to_ipv4() { println!("Обратно в IPv4: {}", back_to_ipv4); } } fn main() { demonstrate_ipv6_conversions(); }
Фильтрация и классификация IPv6 адресов
use std::net::Ipv6Addr; #[derive(Debug)] struct IPv6Classifier; impl IPv6Classifier { fn classify(addr: Ipv6Addr) -> &'static str { if addr.is_unspecified() { "неспецифицированный" } else if addr.is_loopback() { "обратная петля" } else if addr.is_multicast() { "многоадресный" } else if addr.is_unicast_link_local() { "unicast link-local" } else if addr.is_unique_local() { "unique local" } else if addr.is_documentation() { "документация" } else if addr.is_unicast_global() { "unicast global" } else if addr.is_global() { "глобальный" } else { "неизвестный тип" } } fn is_private(addr: Ipv6Addr) -> bool { addr.is_loopback() || addr.is_unicast_link_local() || addr.is_unique_local() || addr.is_unspecified() } fn filter_public_addresses(addrs: Vec<Ipv6Addr>) -> Vec<Ipv6Addr> { addrs.into_iter() .filter(|&addr| !Self::is_private(addr) && addr.is_global()) .collect() } } fn main() { let test_addresses = vec![ Ipv6Addr::UNSPECIFIED, Ipv6Addr::LOCALHOST, Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), Ipv6Addr::new(0xfd00, 0, 0, 0, 0, 0, 0, 1), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111), // Cloudflare DNS ]; println!("Классификация IPv6 адресов:"); for addr in &test_addresses { let classification = IPv6Classifier::classify(*addr); let is_private = IPv6Classifier::is_private(*addr); println!(" {} -> {} {}", addr, classification, if is_private { "(private)" } else { "(public)" }); } let public_addrs = IPv6Classifier::filter_public_addresses(test_addresses); println!("\nПубличные адреса:"); for addr in public_addrs { println!(" {}", addr); } }
Работа с многоадресными адресами
use std::net::{Ipv6Addr, Ipv6MulticastScope}; fn analyze_multicast() { let multicast_addresses = [ Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 1), // Interface-local Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1), // Link-local Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 0, 1), // Site-local Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 1), // Global ]; println!("Анализ многоадресных IPv6 адресов:"); for addr in multicast_addresses { println!("\nАдрес: {}", addr); println!(" Сегменты: {:x?}", addr.segments()); if let Some(scope) = addr.multicast_scope() { println!(" Область: {:?}", scope); match scope { Ipv6MulticastScope::InterfaceLocal => { println!(" Описание: В пределах одного интерфейса"); } Ipv6MulticastScope::LinkLocal => { println!(" Описание: В пределах одной ссылки"); } Ipv6MulticastScope::RealmLocal => { println!(" Описание: В пределах REALM"); } Ipv6MulticastScope::AdminLocal => { println!(" Описание: Административно ограниченная область"); } Ipv6MulticastScope::SiteLocal => { println!(" Описание: В пределах одного сайта"); } Ipv6MulticastScope::OrganizationLocal => { println!(" Описание: В пределах одной организации"); } Ipv6MulticastScope::Global => { println!(" Описание: Глобальная область"); } Ipv6MulticastScope::Reserved => { println!(" Описание: Зарезервированная область"); } Ipv6MulticastScope::Unassigned => { println!(" Описание: Не назначенная область"); } } } } } fn main() { analyze_multicast(); }
Структура Incoming
#![allow(unused)] fn main() { pub struct Incoming<'a> { /* приватные поля */ } }
Итератор, который бесконечно accept подключения на TcpListener.
Этот итератор создается методом TcpListener::incoming и никогда не возвращает None. Он также не пропускает ошибки ввода-вывода. Если требуется обработать ошибки, используйте next метод итератора.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); for stream in listener.incoming() { match stream { Ok(stream) => { println!("новое подключение: {}", stream.peer_addr().unwrap()); } Err(e) => { println!("ошибка подключения: {}", e); } } } }
Методы
next
#![allow(unused)] fn main() { impl<'a> Iterator for Incoming<'a> { type Item = Result<TcpStream>; fn next(&mut self) -> Option<Result<TcpStream>> } }
Возвращает следующий элемент итератора.
Поскольку Incoming никогда не возвращает None, этот метод всегда возвращает Some.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; use std::io; let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); let mut incoming = listener.incoming(); // Использование next() в цикле while let Some(result) = incoming.next() { match result { Ok(stream) => { println!("Принято новое подключение: {}", stream.peer_addr().unwrap()); // Обработка потока } Err(e) => { eprintln!("Ошибка при принятии подключения: {}", e); } } } }
Трайт-реализации
Iterator
#![allow(unused)] fn main() { impl<'a> Iterator for Incoming<'a> }
Реализует трейт Iterator для Incoming.
Итератор возвращает Result<TcpStream> и никогда не возвращает None.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); // Использование в for цикле for stream_result in listener.incoming() { match stream_result { Ok(stream) => { println!("Новое подключение от: {}", stream.peer_addr().unwrap()); } Err(e) => { eprintln!("Ошибка: {}", e); } } } }
Debug
#![allow(unused)] fn main() { impl<'a> Debug for Incoming<'a> }
Реализует отладочное отображение для Incoming.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; use std::fmt; let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); let incoming = listener.incoming(); println!("Отладочная информация: {:?}", incoming); }
Примеры использования
Базовое использование с обработкой ошибок
use std::net::{TcpListener, TcpStream}; use std::io::{self, Read, Write}; use std::thread; fn handle_client(mut stream: TcpStream) -> io::Result<()> { let mut buffer = [0; 1024]; // Чтение данных от клиента let bytes_read = stream.read(&mut buffer)?; if bytes_read > 0 { // Эхо-ответ stream.write_all(&buffer[..bytes_read])?; println!("Обработано {} байт от {}", bytes_read, stream.peer_addr()?); } Ok(()) } fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; println!("Сервер запущен на {}", listener.local_addr()?); for stream_result in listener.incoming() { match stream_result { Ok(stream) => { println!("Новое подключение от: {}", stream.peer_addr().unwrap()); // Обработка каждого клиента в отдельном потоке thread::spawn(move || { if let Err(e) = handle_client(stream) { eprintln!("Ошибка обработки клиента: {}", e); } }); } Err(e) => { eprintln!("Ошибка при принятии подключения: {}", e); } } } Ok(()) }
Использование с неблокирующим I/O
use std::net::TcpListener; use std::io; use std::thread; use std::time::Duration; fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; // Установка неблокирующего режима listener.set_nonblocking(true)?; println!("Неблокирующий сервер запущен на {}", listener.local_addr()?); let mut incoming = listener.incoming(); loop { match incoming.next() { Some(Ok(stream)) => { println!("Принято подключение: {}", stream.peer_addr().unwrap()); // Обработка потока } Some(Err(ref e)) if e.kind() == io::ErrorKind::WouldBlock => { // Нет новых подключений - ждем thread::sleep(Duration::from_millis(100)); continue; } Some(Err(e)) => { eprintln!("Ошибка: {}", e); } None => { // Incoming никогда не возвращает None, но компилятор требует обработки unreachable!(); } } } }
Ограничение количества одновременных подключений
use std::net::{TcpListener, TcpStream}; use std::sync::{Arc, Mutex}; use std::collections::HashMap; use std::thread; use std::time::{Duration, Instant}; struct ConnectionManager { connections: Mutex<HashMap<thread::ThreadId, Instant>>, max_connections: usize, } impl ConnectionManager { fn new(max_connections: usize) -> Self { Self { connections: Mutex::new(HashMap::new()), max_connections, } } fn can_accept(&self) -> bool { let connections = self.connections.lock().unwrap(); connections.len() < self.max_connections } fn add_connection(&self, id: thread::ThreadId) { let mut connections = self.connections.lock().unwrap(); connections.insert(id, Instant::now()); } fn remove_connection(&self, id: thread::ThreadId) { let mut connections = self.connections.lock().unwrap(); connections.remove(&id); } fn cleanup_old_connections(&self, max_age: Duration) { let mut connections = self.connections.lock().unwrap(); let now = Instant::now(); connections.retain(|_, &mut timestamp| now.duration_since(timestamp) < max_age); } } fn handle_client(stream: TcpStream, manager: Arc<ConnectionManager>) { let thread_id = thread::current().id(); // Добавляем подключение в менеджер manager.add_connection(thread_id); // Имитация обработки клиента println!("Обработка клиента {} в потоке {:?}", stream.peer_addr().unwrap(), thread_id); thread::sleep(Duration::from_secs(5)); // Удаляем подключение из менеджера manager.remove_connection(thread_id); println!("Завершена обработка клиента в потоке {:?}", thread_id); } fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; let manager = Arc::new(ConnectionManager::new(3)); // Максимум 3 одновременных подключения println!("Сервер с ограничением подключений запущен на {}", listener.local_addr()?); for stream_result in listener.incoming() { // Очистка старых подключений каждую итерацию manager.cleanup_old_connections(Duration::from_secs(10)); if !manager.can_accept() { println!("Достигнут лимит подключений, ожидаем..."); thread::sleep(Duration::from_secs(1)); continue; } match stream_result { Ok(stream) => { let manager_clone = Arc::clone(&manager); thread::spawn(move || { handle_client(stream, manager_clone); }); } Err(e) => { eprintln!("Ошибка при принятии подключения: {}", e); } } } Ok(()) }
Использование с таймаутами
use std::net::TcpListener; use std::io; use std::thread; use std::time::Duration; fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; // Установка таймаута для операций с слушателем listener.set_nonblocking(false)?; println!("Сервер с таймаутами запущен на {}", listener.local_addr()?); let start_time = std::time::Instant::now(); let timeout = Duration::from_secs(30); // 30 секунд работы сервера for stream_result in listener.incoming() { // Проверка таймаута сервера if start_time.elapsed() > timeout { println!("Время работы сервера истекло"); break; } match stream_result { Ok(stream) => { // Установка таймаутов для клиентского потока stream.set_read_timeout(Some(Duration::from_secs(10)))?; stream.set_write_timeout(Some(Duration::from_secs(10)))?; println!("Принято подключение с таймаутами: {}", stream.peer_addr().unwrap()); // Обработка в отдельном потоке thread::spawn(move || { // Обработка клиента println!("Обработка клиента {}", stream.peer_addr().unwrap()); }); } Err(e) => { eprintln!("Ошибка при принятии подключения: {}", e); } } } println!("Сервер завершил работу"); Ok(()) }
Статистика подключений
use std::net::TcpListener; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Instant; #[derive(Debug, Default)] struct ServerStats { total_connections: usize, successful_connections: usize, failed_connections: usize, start_time: Instant, } impl ServerStats { fn new() -> Self { Self { start_time: Instant::now(), ..Default::default() } } fn record_connection(&mut self, success: bool) { self.total_connections += 1; if success { self.successful_connections += 1; } else { self.failed_connections += 1; } } fn print_stats(&self) { let uptime = self.start_time.elapsed(); println!( "Статистика сервера (uptime: {:?}):\n\ Всего подключений: {}\n\ Успешных: {}\n\ Неудачных: {}", uptime, self.total_connections, self.successful_connections, self.failed_connections ); } } fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; let stats = Arc::new(Mutex::new(ServerStats::new())); println!("Сервер со статистикой запущен на {}", listener.local_addr()?); // Поток для вывода статистики let stats_clone = Arc::clone(&stats); thread::spawn(move || { loop { thread::sleep(std::time::Duration::from_secs(10)); let stats = stats_clone.lock().unwrap(); stats.print_stats(); } }); for stream_result in listener.incoming() { let stats = Arc::clone(&stats); match stream_result { Ok(stream) => { { let mut stats = stats.lock().unwrap(); stats.record_connection(true); } println!("Успешное подключение от: {}", stream.peer_addr().unwrap()); thread::spawn(move || { // Обработка клиента println!("Обработка клиента {}", stream.peer_addr().unwrap()); }); } Err(e) => { { let mut stats = stats.lock().unwrap(); stats.record_connection(false); } eprintln!("Неудачное подключение: {}", e); } } } Ok(()) }
Особенности использования
Бесконечный итератор
Incoming никогда не возвращает None, поэтому циклы с ним будут выполняться бесконечно, пока программа не будет прервана.
Обработка ошибок
В отличие от некоторых итераторов, Incoming не пропускает ошибки ввода-вывода. Каждая ошибка должна быть обработана явно.
Блокирующие операции
По умолчанию операции accept блокирующие. Для неблокирующего поведения используйте set_nonblocking.
Владение
Incoming заимствует TcpListener, поэтому слушатель не может быть использован для других операций пока итератор существует.
Структура IntoIncoming
#![allow(unused)] fn main() { pub struct IntoIncoming { /* приватные поля */ } }
🔬 Это экспериментальное API, доступное только в ночных сборках. (tcplistener_into_incoming #88373)
Итератор, который бесконечно принимает подключения на TcpListener.
Эта структура создается методом TcpListener::into_incoming. Смотрите его документацию для получения дополнительной информации.
Примеры
#![allow(unused)] #![feature(tcplistener_into_incoming)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); let mut incoming = listener.into_incoming(); for stream_result in incoming { match stream_result { Ok(stream) => { println!("новое подключение: {}", stream.peer_addr().unwrap()); } Err(e) => { println!("ошибка подключения: {}", e); } } } }
Реализации трейтов
Debug для IntoIncoming
#![allow(unused)] fn main() { impl Debug for IntoIncoming }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result }
Форматирует значение с помощью заданного форматировщика. Подробнее
Iterator для IntoIncoming
#![allow(unused)] fn main() { impl Iterator for IntoIncoming }
Ассоциированный тип Item
#![allow(unused)] fn main() { type Item = Result<TcpStream, Error> }
Тип элементов, по которым выполняется итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<Result<TcpStream>> }
Перемещает итератор вперед и возвращает следующее значение. Подробнее
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326)
Перемещает итератор вперед и возвращает массив, содержащий следующие N значений. Подробнее
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора. Подробнее
count
#![allow(unused)] fn main() { fn count(self) -> usize where Self: Sized, }
Потребляет итератор, подсчитывая количество итераций и возвращая его. Подробнее
last
#![allow(unused)] fn main() { fn last(self) -> Option<Self::Item> where Self: Sized, }
Потребляет итератор, возвращая последний элемент. Подробнее
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404)
Перемещает итератор на n элементов. Подробнее
nth
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора. Подробнее
step_by
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с заданным шагом на каждой итерации. Подробнее
chain
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор по обоим последовательно. Подробнее
zip
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар. Подробнее
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию разделителя между соседними элементами исходного итератора. Подробнее
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный разделителем, между соседними элементами исходного итератора. Подробнее
map
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента. Подробнее
for_each
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора. Подробнее
filter
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан. Подробнее
filter_map
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует. Подробнее
enumerate
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение. Подробнее
peekable
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления. Смотрите их документацию для получения дополнительной информации. Подробнее
skip_while
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката. Подробнее
take_while
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката. Подробнее
map_while
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует. Подробнее
skip
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов. Подробнее
take
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше. Подробнее
scan
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как fold, хранит внутреннее состояние, но в отличие от fold, создает новый итератор. Подробнее
flat_map
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но уплощает вложенную структуру. Подробнее
flatten
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который уплощает вложенную структуру. Подробнее
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого смежного окна размера N над self и возвращает итератор по выводам f. Как и slice::windows(), окна во время отображения также перекрываются. Подробнее
fuse
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который заканчивается после первого None. Подробнее
inspect
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Делает что-то с каждым элементом итератора, передавая значение дальше. Подробнее
by_ref
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для этого экземпляра Iterator. Подробнее
collect
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию. Подробнее
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047)
Преобразует итератор в коллекцию с возможностью ошибки, прерываясь при встрече с ошибкой. Подробнее
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780)
Собирает все элементы из итератора в коллекцию. Подробнее
partition
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него. Подробнее
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все возвращающие true предшествуют всем возвращающим false. Подробнее
try_fold
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию до тех пор, пока она возвращает успех, производя одно конечное значение. Подробнее
try_for_each
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу в итераторе, останавливаясь при первой ошибке и возвращая эту ошибку. Подробнее
fold
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Сворачивает каждый элемент в аккумулятор, применяя операцию, возвращая конечный результат. Подробнее
reduce
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сокращает элементы до одного, повторно применяя операцию сокращения. Подробнее
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053)
Сокращает элементы до одного, повторно применяя операцию сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне. Подробнее
all
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату. Подробнее
any
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли любой элемент итератора предикату. Подробнее
find
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату. Подробнее
find_map
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат. Подробнее
try_find
#![allow(unused)] fn main() { fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178)
Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку. Подробнее
position
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс. Подробнее
max
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора. Подробнее
min
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора. Подробнее
max_by_key
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение из указанной функции. Подробнее
max_by
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения. Подробнее
min_by_key
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение из указанной функции. Подробнее
min_by
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения. Подробнее
unzip
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров. Подробнее
copied
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы. Подробнее
cloned
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы. Подробнее
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450)
Возвращает итератор по N элементам итератора за раз. Подробнее
sum
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора. Подробнее
product
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы. Подробнее
cmp
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого. Подробнее
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения. Подробнее
partial_cmp
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат. Подробнее
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения. Подробнее
eq
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого. Подробнее
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства. Подробнее
ne
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого. Подробнее
lt
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически меньше ли элементы этого Iterator элементов другого. Подробнее
le
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически меньше или равны ли элементы этого Iterator элементам другого. Подробнее
gt
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически больше ли элементы этого Iterator элементов другого. Подробнее
ge
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически больше или равны ли элементы этого Iterator элементам другого. Подробнее
is_sorted
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора. Подробнее
is_sorted_by
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции-компаратора. Подробнее
is_sorted_by_key
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа. Подробнее
FusedIterator для IntoIncoming
#![allow(unused)] fn main() { impl FusedIterator for IntoIncoming }
Реализует трейт FusedIterator, что означает, что после возврата None итератор всегда будет возвращать None.
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl Freeze for IntoIncoming impl RefUnwindSafe for IntoIncoming impl Send for IntoIncoming impl Sync for IntoIncoming impl Unpin for IntoIncoming impl UnwindSafe for IntoIncoming }
Стандартные реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, impl<T> Borrow<T> for T where T: ?Sized, impl<T> BorrowMut<T> for T where T: ?Sized, impl<T> From<T> for T impl<T, U> Into<U> for T where U: From<T>, impl<I> IntoIterator for I where I: Iterator, impl<T, U> TryFrom<U> for T where U: Into<T>, impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Особенности использования
IntoIncoming - это альтернатива Incoming, которая принимает владение TcpListener. Это может быть полезно в сценариях, где вы хотите переместить слушатель в итератор и больше не нуждаетесь в исходном объекте слушателя.
Структура SocketAddrV4
#![allow(unused)] fn main() { pub struct SocketAddrV4 { /* приватные поля */ } }
Адрес интернет-сокса IPv4.
SocketAddrV4 включает в себя адрес IPv4 и номер порта.
См. также SocketAddr для типа, представляющий либо IPv4, либо IPv6 адрес сокета.
Представление в памяти
SocketAddrV4 имеет то же представление в памяти, что и соответствующая структура C sockaddr_in.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); assert_eq!( "127.0.0.1:8080".parse(), Ok(socket) ); }
Методы
new
#![allow(unused)] fn main() { pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 }
Создает новый адрес сокета IPv4 из Ipv4Addr и номера порта.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); assert_eq!(addr.ip(), &Ipv4Addr::new(127, 0, 0, 1)); assert_eq!(addr.port(), 8080); }
ip
#![allow(unused)] fn main() { pub const fn ip(&self) -> &Ipv4Addr }
Возвращает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); }
port
#![allow(unused)] fn main() { pub const fn port(&self) -> u16 }
Возвращает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); assert_eq!(socket.port(), 8080); }
set_ip
#![allow(unused)] fn main() { pub fn set_ip(&mut self, new_ip: Ipv4Addr) }
Устанавливает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); socket.set_ip(Ipv4Addr::new(192, 168, 1, 1)); assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 1, 1)); }
set_port
#![allow(unused)] fn main() { pub fn set_port(&mut self, new_port: u16) }
Устанавливает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv4Addr, SocketAddrV4}; let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); socket.set_port(9090); assert_eq!(socket.port(), 9090); }
Трайт-реализации
From<SocketAddrV4>
#![allow(unused)] fn main() { impl From<SocketAddrV4> for SocketAddr }
Преобразует SocketAddrV4 в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; let socket_v4 = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); let socket_addr = SocketAddr::from(socket_v4); assert_eq!(socket_addr.ip().to_string(), "127.0.0.1"); assert_eq!(socket_addr.port(), 8080); }
Display, Debug
#![allow(unused)] fn main() { impl Display for SocketAddrV4 impl Debug for SocketAddrV4 }
Реализует отображение и отладочное отображение для SocketAddrV4.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddrV4, Ipv4Addr}; let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 8080); println!("Адрес сокета: {}", socket); // "192.168.1.1:8080" println!("Отладочная информация: {:?}", socket); // "192.168.1.1:8080" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for SocketAddrV4 impl Eq for SocketAddrV4 impl PartialOrd for SocketAddrV4 impl Ord for SocketAddrV4 impl Hash for SocketAddrV4 }
Реализует сравнение и хеширование для SocketAddrV4.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddrV4, Ipv4Addr}; use std::collections::HashMap; let socket1 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 8080); let socket2 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 8080); let socket3 = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 8080); assert_eq!(socket1, socket2); assert_ne!(socket1, socket3); let mut map = HashMap::new(); map.insert(socket1, "server1"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for SocketAddrV4 }
Реализует парсинг из строки для SocketAddrV4.
Примеры
#![allow(unused)] fn main() { use std::net::SocketAddrV4; use std::str::FromStr; let socket = SocketAddrV4::from_str("127.0.0.1:8080").unwrap(); assert_eq!(socket.port(), 8080); }
Примеры использования
Создание и манипуляция адресами сокетов IPv4
use std::net::{SocketAddrV4, Ipv4Addr}; fn demonstrate_socketaddr_v4() { // Создание базового адреса сокета let mut socket = SocketAddrV4::new( Ipv4Addr::new(192, 168, 1, 1), 8080, ); println!("Исходный адрес: {}", socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); // Изменение полей socket.set_ip(Ipv4Addr::new(10, 0, 0, 1)); socket.set_port(9090); println!("\nПосле изменений:"); println!(" Адрес: {}", socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); } fn main() { demonstrate_socketaddr_v4(); }
Использование в сетевых операциях
use std::net::{TcpListener, UdpSocket, SocketAddrV4, Ipv4Addr}; use std::io; fn create_ipv4_server() -> io::Result<()> { // Создание TCP слушателя на IPv4 let socket_addr = SocketAddrV4::new( Ipv4Addr::new(0, 0, 0, 0), // 0.0.0.0 (все интерфейсы) 8080, ); let tcp_listener = TcpListener::bind(socket_addr)?; println!("TCP сервер слушает на: {}", tcp_listener.local_addr()?); // Создание UDP сокета на IPv4 let udp_socket = UdpSocket::bind(socket_addr)?; println!("UDP сокет привязан к: {}", udp_socket.local_addr()?); Ok(()) } fn connect_to_ipv4_server() -> io::Result<()> { let server_addr = SocketAddrV4::new( Ipv4Addr::new(127, 0, 0, 1), 8080, ); // Попытка подключения по TCP match std::net::TcpStream::connect(server_addr) { Ok(_stream) => println!("Успешное подключение к серверу"), Err(e) => println!("Ошибка подключения: {}", e), } Ok(()) } fn main() -> io::Result<()> { create_ipv4_server()?; connect_to_ipv4_server()?; Ok(()) }
Преобразование между различными форматами
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; fn demonstrate_conversions() { // Создание SocketAddrV4 let socket_v4 = SocketAddrV4::new( Ipv4Addr::new(192, 168, 1, 1), 8080, ); println!("SocketAddrV4: {}", socket_v4); println!(" IP: {}", socket_v4.ip()); println!(" Порт: {}", socket_v4.port()); // Преобразование в SocketAddr let socket_addr = SocketAddr::from(socket_v4); println!("\nПосле преобразования в SocketAddr:"); println!(" SocketAddr: {}", socket_addr); println!(" IP: {}", socket_addr.ip()); println!(" Порт: {}", socket_addr.port()); println!(" is_ipv4(): {}", socket_addr.is_ipv4()); println!(" is_ipv6(): {}", socket_addr.is_ipv6()); // Обратное преобразование (если это IPv4) if let SocketAddr::V4(socket_v4_again) = socket_addr { println!("\nОбратное преобразование:"); println!(" SocketAddrV4: {}", socket_v4_again); } } fn main() { demonstrate_conversions(); }
Парсинг из строки
use std::net::SocketAddrV4; use std::str::FromStr; fn demonstrate_parsing() { let test_cases = [ "127.0.0.1:8080", "192.168.1.1:80", "0.0.0.0:0", "255.255.255.255:65535", "10.0.0.1:443", ]; println!("Парсинг IPv4 адресов сокетов:"); for test_case in &test_cases { match SocketAddrV4::from_str(test_case) { Ok(socket) => { println!(" ✓ '{}' -> {}", test_case, socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); } Err(e) => { println!(" ✗ '{}' -> Ошибка: {}", test_case, e); } } println!(); } } fn main() { demonstrate_parsing(); }
Работа с различными типами адресов
use std::net::{SocketAddrV4, Ipv4Addr}; fn demonstrate_address_types() { let special_addresses = [ SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 8080), // 0.0.0.0 SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080), // 127.0.0.1 SocketAddrV4::new(Ipv4Addr::BROADCAST, 8080), // 255.255.255.255 SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 8080), // Частный SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 8080), // Частный SocketAddrV4::new(Ipv4Addr::new(172, 16, 0, 1), 8080), // Частный SocketAddrV4::new(Ipv4Addr::new(169, 254, 0, 1), 8080), // Link-local SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 1), 8080), // Multicast ]; println!("Специальные IPv4 адреса сокетов:"); for socket in &special_addresses { let ip = socket.ip(); println!(" Адрес: {}", socket); println!(" Неспецифицированный: {}", ip.is_unspecified()); println!(" Обратная петля: {}", ip.is_loopback()); println!(" Частный: {}", ip.is_private()); println!(" Link-local: {}", ip.is_link_local()); println!(" Многоадресный: {}", ip.is_multicast()); println!(" Широковещательный: {}", ip.is_broadcast()); println!(); } } fn main() { demonstrate_address_types(); }
Использование в коллекциях
use std::net::{SocketAddrV4, Ipv4Addr}; use std::collections::{HashMap, HashSet}; fn demonstrate_collections() { // Создание нескольких адресов сокетов let addresses = vec![ SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 80), SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 443), SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 2), 80), SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 8080), ]; // Использование в HashSet (уникальные адреса) let unique_addresses: HashSet<_> = addresses.iter().collect(); println!("Уникальные адреса в HashSet:"); for addr in &unique_addresses { println!(" {}", addr); } // Использование в HashMap let mut server_map = HashMap::new(); server_map.insert( SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 80), "Веб-сервер", ); server_map.insert( SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 443), "HTTPS-сервер", ); server_map.insert( SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 8080), "Внутренний сервер", ); println!("\nСерверы в HashMap:"); for (addr, description) in &server_map { println!(" {} -> {}", addr, description); } // Поиск в коллекциях let search_addr = SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 80); if let Some(description) = server_map.get(&search_addr) { println!("\nНайден сервер: {} -> {}", search_addr, description); } } fn main() { demonstrate_collections(); }
Особенности IPv4 сокетов
Представление в памяти
Совместимо с системной структурой sockaddr_in, что позволяет напрямую использовать в системных вызовах.
Сравнение и хеширование
Два SocketAddrV4 считаются равными, если у них одинаковый IP-адрес и порт. Это позволяет использовать их как ключи в HashMap и HashSet.
Преобразования
Легко преобразуется в и из SocketAddr, что обеспечивает гибкость при работе с кодом, который должен поддерживать как IPv4, так и IPv6.
Структура SocketAddrV6
#![allow(unused)] fn main() { pub struct SocketAddrV6 { /* приватные поля */ } }
Адрес интернет-сокса IPv6.
SocketAddrV6 включает в себя адрес IPv6, номер порта, а также поля flow information и scope ID, как определено в RFC 2553, Section 3.3.
Для получения дополнительной информации о полях flow information и scope ID смотрите IETF RFC 3493, Section 3.3 и IETF RFC 3542, Section 6.
См. также SocketAddr для типа, представляющий либо IPv4, либо IPv6 адрес сокета.
Представление в памяти
SocketAddrV6 имеет то же представление в памяти, что и соответствующая структура C sockaddr_in6.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); assert_eq!( "[2001:db8::1]:8080".parse(), Ok(socket) ); }
Методы
new
#![allow(unused)] fn main() { pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 }
Создает новый адрес сокета IPv6 из Ipv6Addr, номера порта, flow information и scope ID.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let addr = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); assert_eq!(addr.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); assert_eq!(addr.port(), 8080); }
ip
#![allow(unused)] fn main() { pub const fn ip(&self) -> &Ipv6Addr }
Возвращает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); }
port
#![allow(unused)] fn main() { pub const fn port(&self) -> u16 }
Возвращает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); assert_eq!(socket.port(), 8080); }
flowinfo
#![allow(unused)] fn main() { pub const fn flowinfo(&self) -> u32 }
Возвращает flow information, связанную с этим адресом сокета.
Эта информация соответствует полю sin6_flowinfo в структуре sockaddr_in6.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 42, 0, ); assert_eq!(socket.flowinfo(), 42); }
scope_id
#![allow(unused)] fn main() { pub const fn scope_id(&self) -> u32 }
Возвращает scope ID, связанную с этим адресом сокета.
Эта информация соответствует полю sin6_scope_id в структуре sockaddr_in6 и используется для идентификации зоны ссылки для адресов link-local.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let socket = SocketAddrV6::new( Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 3, ); assert_eq!(socket.scope_id(), 3); }
set_ip
#![allow(unused)] fn main() { pub fn set_ip(&mut self, new_ip: Ipv6Addr) }
Устанавливает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let mut socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); socket.set_ip(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)); assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)); }
set_port
#![allow(unused)] fn main() { pub fn set_port(&mut self, new_port: u16) }
Устанавливает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let mut socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); socket.set_port(9090); assert_eq!(socket.port(), 9090); }
set_flowinfo
#![allow(unused)] fn main() { pub fn set_flowinfo(&mut self, new_flowinfo: u32) }
Устанавливает flow information, связанную с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let mut socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); socket.set_flowinfo(123); assert_eq!(socket.flowinfo(), 123); }
set_scope_id
#![allow(unused)] fn main() { pub fn set_scope_id(&mut self, new_scope_id: u32) }
Устанавливает scope ID, связанную с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{Ipv6Addr, SocketAddrV6}; let mut socket = SocketAddrV6::new( Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); socket.set_scope_id(5); assert_eq!(socket.scope_id(), 5); }
Трайт-реализации
From<SocketAddrV6>
#![allow(unused)] fn main() { impl From<SocketAddrV6> for SocketAddr }
Преобразует SocketAddrV6 в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, SocketAddrV6, Ipv6Addr}; let socket_v6 = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); let socket_addr = SocketAddr::from(socket_v6); assert_eq!(socket_addr.ip().to_string(), "2001:db8::1"); assert_eq!(socket_addr.port(), 8080); }
Display, Debug
#![allow(unused)] fn main() { impl Display for SocketAddrV6 impl Debug for SocketAddrV6 }
Реализует отображение и отладочное отображение для SocketAddrV6.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddrV6, Ipv6Addr}; let socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); println!("Адрес сокета: {}", socket); // "[2001:db8::1]:8080" println!("Отладочная информация: {:?}", socket); // "[2001:db8::1]:8080" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for SocketAddrV6 impl Eq for SocketAddrV6 impl PartialOrd for SocketAddrV6 impl Ord for SocketAddrV6 impl Hash for SocketAddrV6 }
Реализует сравнение и хеширование для SocketAddrV6.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddrV6, Ipv6Addr}; use std::collections::HashMap; let socket1 = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); let socket2 = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); let socket3 = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2), 8080, 0, 0, ); assert_eq!(socket1, socket2); assert_ne!(socket1, socket3); let mut map = HashMap::new(); map.insert(socket1, "server1"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for SocketAddrV6 }
Реализует парсинг из строки для SocketAddrV6.
Примеры
#![allow(unused)] fn main() { use std::net::SocketAddrV6; use std::str::FromStr; let socket = SocketAddrV6::from_str("[2001:db8::1]:8080").unwrap(); assert_eq!(socket.port(), 8080); }
Примеры использования
Создание и манипуляция адресами сокетов IPv6
use std::net::{SocketAddrV6, Ipv6Addr}; fn demonstrate_socketaddr_v6() { // Создание базового адреса сокета let mut socket = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); println!("Исходный адрес: {}", socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); println!(" Flowinfo: {}", socket.flowinfo()); println!(" Scope ID: {}", socket.scope_id()); // Изменение полей socket.set_ip(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)); socket.set_port(9090); socket.set_flowinfo(123); socket.set_scope_id(5); println!("\nПосле изменений:"); println!(" Адрес: {}", socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); println!(" Flowinfo: {}", socket.flowinfo()); println!(" Scope ID: {}", socket.scope_id()); } fn main() { demonstrate_socketaddr_v6(); }
Работа с link-local адресами и scope ID
use std::net::{SocketAddrV6, Ipv6Addr}; fn demonstrate_link_local() { // Link-local адреса требуют указания scope ID let link_local_sockets = [ SocketAddrV6::new( Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 1, // scope ID для интерфейса 1 ), SocketAddrV6::new( Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 2, // scope ID для интерфейса 2 ), ]; println!("Link-local адреса сокетов:"); for socket in &link_local_sockets { println!(" Адрес: {}", socket); println!(" Scope ID: {}", socket.scope_id()); println!(" Link-local: {}", socket.ip().is_unicast_link_local()); } // Демонстрация, что разные scope ID создают разные сокеты let socket1 = &link_local_sockets[0]; let socket2 = &link_local_sockets[1]; println!("\nСравнение:"); println!(" socket1 == socket2: {}", socket1 == socket2); println!(" socket1.ip() == socket2.ip(): {}", socket1.ip() == socket2.ip()); println!(" socket1.scope_id() == socket2.scope_id(): {}", socket1.scope_id() == socket2.scope_id()); } fn main() { demonstrate_link_local(); }
Использование в сетевых операциях
use std::net::{TcpListener, UdpSocket, SocketAddrV6, Ipv6Addr}; use std::io; fn create_ipv6_server() -> io::Result<()> { // Создание TCP слушателя на IPv6 let socket_addr = SocketAddrV6::new( Ipv6Addr::UNSPECIFIED, // :: (все интерфейсы) 8080, 0, 0, ); let tcp_listener = TcpListener::bind(socket_addr)?; println!("TCP сервер слушает на: {}", tcp_listener.local_addr()?); // Создание UDP сокета на IPv6 let udp_socket = UdpSocket::bind(socket_addr)?; println!("UDP сокет привязан к: {}", udp_socket.local_addr()?); Ok(()) } fn connect_to_ipv6_server() -> io::Result<()> { let server_addr = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0, ); // Попытка подключения по TCP match std::net::TcpStream::connect(server_addr) { Ok(_stream) => println!("Успешное подключение к серверу"), Err(e) => println!("Ошибка подключения: {}", e), } Ok(()) } fn main() -> io::Result<()> { create_ipv6_server()?; connect_to_ipv6_server()?; Ok(()) }
Преобразование между различными форматами
use std::net::{SocketAddr, SocketAddrV6, Ipv6Addr}; fn demonstrate_conversions() { // Создание SocketAddrV6 let socket_v6 = SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 123, 5, ); println!("SocketAddrV6: {}", socket_v6); println!(" IP: {}", socket_v6.ip()); println!(" Порт: {}", socket_v6.port()); println!(" Flowinfo: {}", socket_v6.flowinfo()); println!(" Scope ID: {}", socket_v6.scope_id()); // Преобразование в SocketAddr let socket_addr = SocketAddr::from(socket_v6); println!("\nПосле преобразования в SocketAddr:"); println!(" SocketAddr: {}", socket_addr); println!(" IP: {}", socket_addr.ip()); println!(" Порт: {}", socket_addr.port()); println!(" is_ipv4(): {}", socket_addr.is_ipv4()); println!(" is_ipv6(): {}", socket_addr.is_ipv6()); // Обратное преобразование (если это IPv6) if let SocketAddr::V6(socket_v6_again) = socket_addr { println!("\nОбратное преобразование:"); println!(" SocketAddrV6: {}", socket_v6_again); println!(" Flowinfo: {}", socket_v6_again.flowinfo()); println!(" Scope ID: {}", socket_v6_again.scope_id()); } } fn main() { demonstrate_conversions(); }
Парсинг из строки
use std::net::SocketAddrV6; use std::str::FromStr; fn demonstrate_parsing() { let test_cases = [ "[2001:db8::1]:8080", "[::1]:80", "[fe80::1%eth0]:8080", // С scope ID "[2001:db8:85a3::8a2e:370:7334]:443", ]; println!("Парсинг IPv6 адресов сокетов:"); for test_case in &test_cases { match SocketAddrV6::from_str(test_case) { Ok(socket) => { println!(" ✓ '{}' -> {}", test_case, socket); println!(" IP: {}", socket.ip()); println!(" Порт: {}", socket.port()); println!(" Flowinfo: {}", socket.flowinfo()); println!(" Scope ID: {}", socket.scope_id()); } Err(e) => { println!(" ✗ '{}' -> Ошибка: {}", test_case, e); } } println!(); } } fn main() { demonstrate_parsing(); }
Использование flow information
use std::net::{SocketAddrV6, Ipv6Addr}; fn demonstrate_flowinfo() { // Flow information используется для QoS (Quality of Service) // и управления трафиком в IPv6 let sockets_with_flowinfo = [ SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0x00000000, // Без flow information 0, ), SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0x12345678, // С flow information 0, ), SocketAddrV6::new( Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0x80000000, // Flow label для реального времени 0, ), ]; println!("Адреса сокетов с flow information:"); for socket in &sockets_with_flowinfo { println!(" Адрес: {}", socket); println!(" Flowinfo: 0x{:08x}", socket.flowinfo()); // Анализ flow information let flowinfo = socket.flowinfo(); let flow_label = (flowinfo >> 12) & 0x000FFFFF; // 20 бит flow label let traffic_class = (flowinfo >> 4) & 0x000000FF; // 8 бит traffic class println!(" Flow Label: 0x{:05x}", flow_label); println!(" Traffic Class: 0x{:02x}", traffic_class); if flow_label != 0 { println!(" → Пакеты с flow label могут получать специальную обработку"); } } } fn main() { demonstrate_flowinfo(); }
Особенности IPv6 сокетов
Flow Information
- Используется для QoS и управления трафиком
- Содержит 20-битный flow label и 8-битный traffic class
- Помогает идентифицировать потоки пакетов для специальной обработки
Scope ID
- Требуется для link-local адресов (
fe80::/10) - Идентифицирует конкретный сетевой интерфейс
- Разные scope ID создают разные сокеты, даже с одинаковым IP
Представление в памяти
Совместимо с системной структурой sockaddr_in6, что позволяет напрямую использовать в системных вызовах.
Структура TcpListener
#![allow(unused)] fn main() { pub struct TcpListener(_); }
TCP-сервер, прослушивающий подключения.
После создания TcpListener путем привязки к адресу сокета, он прослушивает входящие TCP-подключения. Эти подключения могут быть приняты путем вызова accept или через итерацию по incoming, возвращающему итератор.
Сокет будет закрыт, когда структура выйдет из области видимости.
Трансмиссия Control Protocol определяется в IETF RFC 793.
NOTE: Эта структура доступна в crate std для платформ wasm32-unknown-unknown, начиная с Rust 1.39.0, но в настоящее время она поддерживает только клиентские сокеты и не поддерживает серверные сокеты.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); for stream in listener.incoming() { match stream { Ok(stream) => { println!("новое подключение: {}", stream.peer_addr().unwrap()); } Err(e) => { println!("ошибка подключения: {}", e); } } } }
Методы
bind
#![allow(unused)] fn main() { pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<TcpListener> }
Создает новый TcpListener, который будет привязан к указанному адресу.
Возвращаемый TcpListener готов для принятия подключений.
Адрес типа A может быть любым типом, реализующим ToSocketAddrs. Смотрите его документацию для примеров.
Если addr дает несколько адресов, bind попытается привязаться к каждому из них, пока один не сработает. Если ни один из адресов не работает, возвращается ошибка от последней попытки.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); }
local_addr
#![allow(unused)] fn main() { pub fn local_addr(&self) -> Result<SocketAddr> }
Возвращает локальный адрес сокета этого слушателя.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); println!("адрес: {:?}", listener.local_addr().unwrap()); }
try_clone
#![allow(unused)] fn main() { pub fn try_clone(&self) -> Result<TcpListener> }
Создает новый независимо владеемый дескриптор того же нижележащего сокета.
Возвращенный TcpListener является ссылкой на тот же сокет, что и этот объект. Оба дескриптора могут использоваться для принятия подключений, и они будут обрабатывать разные подключения.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); let listener_clone = listener.try_clone().unwrap(); }
accept
#![allow(unused)] fn main() { pub fn accept(&self) -> Result<(TcpStream, SocketAddr)> }
Принимает новое входящее подключение из этого слушателя.
Эта функция будет блокировать вызывающий поток, пока не будет установлено новое подключение. Когда установлено подключение, соответствующее TcpStream и удаленный адрес будут возвращены.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); match listener.accept() { Ok((_socket, addr)) => println!("новое подключение: {}", addr), Err(e) => println!("не удалось принять подключение: {}", e), } }
incoming
#![allow(unused)] fn main() { pub fn incoming(&self) -> Incoming<'_> }
Возвращает итератор по подключениям, принимаемым этим слушателем.
Итератор никогда не возвращает None и также не содержит ошибок ввода-вывода. Вместо этого ошибки ввода-вывода могут быть получены при вызове next итератора.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); for stream in listener.incoming() { match stream { Ok(stream) => { println!("новое подключение: {}", stream.peer_addr().unwrap()); } Err(e) => { println!("ошибка подключения: {}", e); } } } }
set_ttl
#![allow(unused)] fn main() { pub fn set_ttl(&self, ttl: u32) -> Result<()> }
Устанавливает значение параметра IP_TTL для этого сокета.
Этот параметр устанавливает время жизни (Time-To-Live) для пакетов, отправленных из этого сокета.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); listener.set_ttl(100).expect("не удалось установить TTL"); }
ttl
#![allow(unused)] fn main() { pub fn ttl(&self) -> Result<u32> }
Получает значение параметра IP_TTL для этого сокета.
Для получения дополнительной информации смотрите set_ttl.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); listener.set_ttl(100).expect("не удалось установить TTL"); assert_eq!(listener.ttl().unwrap_or(0), 100); }
set_only_v6
#![allow(unused)] fn main() { pub fn set_only_v6(&self, only_v6: bool) -> Result<()> }
Устанавливает значение IPV6_V6ONLY для этого сокета.
Если это значение true, то сокет может быть привязан только к IPv6-адресам, и IPv4-подключения не будут приниматься сокетом, привязанным к IPv6-адресу.
Если это значение false, то сокет может быть привязан к IPv6-адресам, и IPv4-подключения будут приняты через IPv4-отображение на IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); listener.set_only_v6(false).expect("не удалось установить only_v6"); }
only_v6
#![allow(unused)] fn main() { pub fn only_v6(&self) -> Result<bool> }
Получает значение параметра IPV6_V6ONLY для этого сокета.
Для получения дополнительной информации смотрите set_only_v6.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); listener.set_only_v6(false).expect("не удалось установить only_v6"); assert_eq!(listener.only_v6().unwrap_or(true), false); }
take_error
#![allow(unused)] fn main() { pub fn take_error(&self) -> Result<Option<Error>> }
Получает значение параметра сокета SO_ERROR.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; let listener = TcpListener::bind("127.0.0.1:80").unwrap(); if let Ok(Some(error)) = listener.take_error() { println!("ошибка сокета: {}", error); } }
set_nonblocking
#![allow(unused)] fn main() { pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> }
Переводит сокет в неблокирующий режим.
Если nonblocking равно true, то операции над сокетом, которые блокировали бы, будут возвращать ошибки вместо блокировки. Если nonblocking равно false, то сокет будет работать в блокирующем режиме.
Примеры
#![allow(unused)] fn main() { use std::net::TcpListener; use std::thread; use std::io; let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); listener.set_nonblocking(true).expect("не удалось установить неблокирующий режим"); thread::spawn(move || { for stream in listener.incoming() { match stream { Ok(s) => { // обрабатываем поток } Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { // ждем, пока сокет станет готовым thread::sleep(std::time::Duration::from_millis(100)); continue; } Err(e) => panic!("неожиданная ошибка ввода-вывода: {}", e), } } }); }
Трайт-реализации
AsFd
#![allow(unused)] fn main() { impl AsFd for TcpListener }
Используется операционной системой для представления низкоуровневого дескриптора файла.
AsRawFd
#![allow(unused)] fn main() { impl AsRawFd for TcpListener }
Представляет необработанный дескриптор файла.
From<TcpListener>
#![allow(unused)] fn main() { impl From<TcpListener> for Arc<TcpListener> }
Преобразует TcpListener в Arc<TcpListener>.
From<TcpListener>
#![allow(unused)] fn main() { impl From<TcpListener> for Socket }
Преобразует TcpListener в Socket.
IntoRawFd
#![allow(unused)] fn main() { impl IntoRawFd for TcpListener }
Потребляет этот объект, возвращая необработанный дескриптор файла.
Debug
#![allow(unused)] fn main() { impl Debug for TcpListener }
Реализует отладочное отображение для TcpListener.
Связанные функции
socket2
#![allow(unused)] fn main() { impl TcpListener }
Расширенные операции, доступные при включении функции net в крейте socket2.
Примечания
- Сокет автоматически закрывается при выходе из области видимости
- Все методы блокирующие, если не установлен неблокирующий режим
- Для асинхронных операций используйте крейты
async-stdилиtokio
Структура TcpStream
#![allow(unused)] fn main() { pub struct TcpStream(_); }
TCP-поток между локальным и удаленным сокетом.
После создания TcpStream путем подключения к удаленному узлу или accept подключения от TcpListener, данные могут быть отправлены через Write и получены через Read.
Клонирование TcpStream создаст новый дескриптор того же самого потока. Оба дескриптора могут использоваться для чтения и записи, и они будут совместно использовать один и тот же поток ввода-вывода.
Трансмиссия Control Protocol определяется в IETF RFC 793.
NOTE: Эта структура доступна в crate std для платформ wasm32-unknown-unknown, начиная с Rust 1.39.0, но в настоящее время она поддерживает только клиентские сокеты и не поддерживает серверные сокеты.
Примеры
use std::io::prelude::*; use std::net::TcpStream; fn main() -> std::io::Result<()> { // Подключение к порту 8080 localhost let mut stream = TcpStream::connect("127.0.0.1:8080")?; // Запись байтов в поток stream.write(&[1])?; stream.write_all(&[2, 3, 4])?; // Чтение ответа let mut buf = [0; 10]; let n = stream.read(&mut buf)?; println!("Прочитано {} байт: {:?}", n, &buf[..n]); Ok(()) }
Методы
connect
#![allow(unused)] fn main() { pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<TcpStream> }
Открывает TCP-подключение к удаленному адресу.
addr - это адрес удаленного узла. Любой допустимый SocketAddr может быть передан, и если задано несколько адресов, будет предпринята попытка подключения к каждому из них по порядку, пока подключение не будет успешно установлено. Если ни одна из попыток не увенчается успехом, возвращается ошибка последней попытки.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; if let Ok(stream) = TcpStream::connect("127.0.0.1:8080") { println!("Подключение установлено!"); } else { println!("Не удалось подключиться"); } }
peer_addr
#![allow(unused)] fn main() { pub fn peer_addr(&self) -> Result<SocketAddr> }
Возвращает адрес сокета удаленного узла этого подключения.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); println!("Подключен к {}", stream.peer_addr().unwrap()); }
local_addr
#![allow(unused)] fn main() { pub fn local_addr(&self) -> Result<SocketAddr> }
Возвращает адрес локального сокета этого подключения.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); println!("Локальный адрес: {}", stream.local_addr().unwrap()); }
shutdown
#![allow(unused)] fn main() { pub fn shutdown(&self, how: Shutdown) -> Result<()> }
Отключает часть подключения.
how определяет, какая часть подключения должна быть отключена:
Shutdown::Read- запрещает дальнейшие операции чтенияShutdown::Write- запрещает дальнейшие операции записиShutdown::Both- запрещает как чтение, так и запись
Примеры
#![allow(unused)] fn main() { use std::net::{TcpStream, Shutdown}; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.shutdown(Shutdown::Both).expect("Ошибка отключения"); }
try_clone
#![allow(unused)] fn main() { pub fn try_clone(&self) -> Result<TcpStream> }
Создает новый независимо владеющий дескриптор того же самого потока.
Возвращенный TcpStream является ссылкой на тот же поток, что и этот объект. Оба дескриптора могут использоваться для чтения и записи, и они будут совместно использовать один и тот же поток ввода-вывода.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::thread; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); let stream_clone = stream.try_clone().unwrap(); thread::spawn(move || { // Использование stream_clone в другом потоке }); }
set_read_timeout
#![allow(unused)] fn main() { pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()> }
Устанавливает таймаут чтения для этого потока.
Если значение равно None, то операции read будут блокироваться бесконечно. Если значение равно Some(Duration), то операции read будут таймаутировать по истечении указанного времени. Если таймаут происходит, возвращается ошибка TimedOut.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_read_timeout(Some(Duration::from_secs(5))).expect("Не удалось установить таймаут чтения"); }
set_write_timeout
#![allow(unused)] fn main() { pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()> }
Устанавливает таймаут записи для этого потока.
Если значение равно None, то операции write будут блокироваться бесконечно. Если значение равно Some(Duration), то операции write будут таймаутировать по истечении указанного времени. Если таймаут происходит, возвращается ошибка TimedOut.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_write_timeout(Some(Duration::from_secs(5))).expect("Не удалось установить таймаут записи"); }
read_timeout
#![allow(unused)] fn main() { pub fn read_timeout(&self) -> Result<Option<Duration>> }
Возвращает текущий таймаут чтения для этого сокета.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); assert_eq!(stream.read_timeout().unwrap(), Some(Duration::from_secs(5))); }
write_timeout
#![allow(unused)] fn main() { pub fn write_timeout(&self) -> Result<Option<Duration>> }
Возвращает текущий таймаут записи для этого сокета.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); assert_eq!(stream.write_timeout().unwrap(), Some(Duration::from_secs(5))); }
set_ttl
#![allow(unused)] fn main() { pub fn set_ttl(&self, ttl: u32) -> Result<()> }
Устанавливает значение параметра IP_TTL для этого сокета.
Этот параметр устанавливает время жизни (Time-To-Live) для пакетов, отправленных из этого сокета.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_ttl(100).expect("Не удалось установить TTL"); }
ttl
#![allow(unused)] fn main() { pub fn ttl(&self) -> Result<u32> }
Получает значение параметра IP_TTL для этого сокета.
Для получения дополнительной информации смотрите set_ttl.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_ttl(100).expect("Не удалось установить TTL"); assert_eq!(stream.ttl().unwrap_or(0), 100); }
set_nodelay
#![allow(unused)] fn main() { pub fn set_nodelay(&self, nodelay: bool) -> Result<()> }
Устанавливает значение параметра TCP_NODELAY для этого сокета.
Если установлено true, то пакеты будут отправляться как можно скорее, без задержки для объединения небольших пакетов.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_nodelay(true).expect("Не удалось установить nodelay"); }
nodelay
#![allow(unused)] fn main() { pub fn nodelay(&self) -> Result<bool> }
Получает значение параметра TCP_NODELAY для этого сокета.
Для получения дополнительной информации смотрите set_nodelay.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_nodelay(true).expect("Не удалось установить nodelay"); assert_eq!(stream.nodelay().unwrap_or(false), true); }
set_linger
#![allow(unused)] fn main() { pub fn set_linger(&self, linger: Option<Duration>) -> Result<()> }
Устанавливает значение параметра SO_LINGER для этого сокета.
Этот параметр управляет поведением сокета при вызове close, когда в отправной очереди остались данные. Если установлено Some(Duration), то close будет блокироваться до тех пор, пока все данные не будут отправлены или не истечет указанное время. Если установлено None, то close вернется немедленно.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_linger(Some(Duration::from_secs(5))).expect("Не удалось установить linger"); }
linger
#![allow(unused)] fn main() { pub fn linger(&self) -> Result<Option<Duration>> }
Получает значение параметра SO_LINGER для этого сокета.
Для получения дополнительной информации смотрите set_linger.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::time::Duration; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_linger(Some(Duration::from_secs(5))).unwrap(); assert_eq!(stream.linger().unwrap(), Some(Duration::from_secs(5))); }
take_error
#![allow(unused)] fn main() { pub fn take_error(&self) -> Result<Option<Error>> }
Получает значение параметра сокета SO_ERROR.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); if let Ok(Some(error)) = stream.take_error() { println!("Ошибка сокета: {}", error); } }
set_nonblocking
#![allow(unused)] fn main() { pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> }
Переводит сокет в неблокирующий режим.
Если nonblocking равно true, то операции над сокетом, которые блокировали бы, будут возвращать ошибки вместо блокировки. Если nonblocking равно false, то сокет будет работать в блокирующем режиме.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; use std::io; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); stream.set_nonblocking(true).expect("Не удалось установить неблокирующий режим"); let mut buf = [0; 10]; match stream.read(&mut buf) { Ok(n) => println!("Прочитано {} байт", n), Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { // Данные пока не доступны } Err(e) => panic!("Неожиданная ошибка ввода-вывода: {}", e), } }
peek
#![allow(unused)] fn main() { pub fn peek(&self, buf: &mut [u8]) -> Result<usize> }
Читает данные из потока без удаления их из буфера.
Эта функция работает как read, но данные, прочитанные через peek, остаются доступными для последующих вызовов read.
Примеры
#![allow(unused)] fn main() { use std::net::TcpStream; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); let mut buf = [0; 10]; let n = stream.peek(&mut buf).expect("Ошибка peek"); println!("Просмотрено {} байт: {:?}", n, &buf[..n]); }
Трайт-реализации
Read, Write
#![allow(unused)] fn main() { impl Read for TcpStream impl Write for TcpStream }
Реализует операции чтения и записи для потока.
AsFd, AsRawFd, IntoRawFd
#![allow(unused)] fn main() { impl AsFd for TcpStream impl AsRawFd for TcpStream impl IntoRawFd for TcpStream }
Предоставляет доступ к низкоуровневому дескриптору файла.
From<TcpStream>
#![allow(unused)] fn main() { impl From<TcpStream> for Arc<TcpStream> impl From<TcpStream> for Socket }
Преобразует TcpStream в Arc<TcpStream> и Socket.
Debug
#![allow(unused)] fn main() { impl Debug for TcpStream }
Реализует отладочное отображение для TcpStream.
Пример использования
use std::io::{Read, Write}; use std::net::TcpStream; use std::thread; use std::time::Duration; fn main() -> std::io::Result<()> { let mut stream = TcpStream::connect("127.0.0.1:8080")?; // Настройка параметров сокета stream.set_nodelay(true)?; stream.set_ttl(64)?; stream.set_read_timeout(Some(Duration::from_secs(10)))?; // Отправка данных stream.write_all(b"Hello, server!")?; // Чтение ответа let mut response = String::new(); stream.read_to_string(&mut response)?; println!("Получен ответ: {}", response); Ok(()) }
Структура UdpSocket
#![allow(unused)] fn main() { pub struct UdpSocket(_); }
UDP-сокет.
User Datagram Protocol (UDP) определяется в IETF RFC 768.
После создания UdpSocket путем привязки к адресу сокета, данные могут быть отправлены и получены с помощью методов этого типа.
NOTE: Эта структура доступна в crate std для платформ wasm32-unknown-unknown, начиная с Rust 1.39.0, но в настоящее время она поддерживает только клиентские сокеты и не поддерживает серверные сокеты.
Примеры
use std::net::UdpSocket; fn main() -> std::io::Result<()> { { let socket = UdpSocket::bind("127.0.0.1:34254")?; // Читаем из сокета let mut buf = [0; 1024]; let (amt, src) = socket.recv_from(&mut buf)?; // Отправляем ответ let buf = &mut buf[..amt]; buf.reverse(); socket.send_to(buf, &src)?; } // сокет закрывается здесь Ok(()) }
Методы
bind
#![allow(unused)] fn main() { pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket> }
Создает новый UDP-сокет из заданного адреса.
Адрес типа A может быть любым типом, реализующим ToSocketAddrs. Смотрите его документацию для примеров.
Если addr дает несколько адресов, bind попытается привязаться к каждому из них, пока один не сработает. Если ни один из адресов не работает, возвращается ошибка от последней попытки.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); }
peer_addr
#![allow(unused)] fn main() { pub fn peer_addr(&self) -> Result<SocketAddr> }
Возвращает адрес сокета удаленного узла, к которому подключен этот сокет.
Этот сокет должен быть подключен с помощью connect.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.connect("127.0.0.1:8080").unwrap(); println!("Подключен к {}", socket.peer_addr().unwrap()); }
local_addr
#![allow(unused)] fn main() { pub fn local_addr(&self) -> Result<SocketAddr> }
Возвращает адрес локального сокета этого подключения.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); println!("Локальный адрес: {}", socket.local_addr().unwrap()); }
connect
#![allow(unused)] fn main() { pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> Result<()> }
Подключает этот UDP-сокет к удаленному адресу.
Когда сокет подключен, методы send и recv будут использовать указанный адрес для отправки и получения данных. Кроме того, будут отфильтрованы пакеты, поступающие с других адресов.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.connect("127.0.0.1:8080").expect("Не удалось подключиться"); }
send
#![allow(unused)] fn main() { pub fn send(&self, buf: &[u8]) -> Result<usize> }
Отправляет данные в удаленный адрес, к которому подключен этот сокет.
Сокет должен быть подключен с помощью connect перед вызовом этого метода.
Возвращает количество записанных байт.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.connect("127.0.0.1:8080").unwrap(); socket.send(&[0; 10]).expect("Не удалось отправить данные"); }
recv
#![allow(unused)] fn main() { pub fn recv(&self, buf: &mut [u8]) -> Result<usize> }
Получает данные из сокета.
Сокет должен быть подключен с помощью connect перед вызовом этого метода.
Возвращает количество прочитанных байт.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.connect("127.0.0.1:8080").unwrap(); let mut buf = [0; 10]; let amt = socket.recv(&mut buf).expect("Не удалось получить данные"); println!("Получено {} байт", amt); }
send_to
#![allow(unused)] fn main() { pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> Result<usize> }
Отправляет данные по указанному адресу.
В отличие от send, этот метод может использоваться без предварительного подключения к адресу.
Возвращает количество записанных байт.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.send_to(&[0; 10], "127.0.0.1:8080").expect("Не удалось отправить данные"); }
recv_from
#![allow(unused)] fn main() { pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> }
Получает данные из сокета и возвращает адрес отправителя.
Возвращает кортеж (количество_байт, адрес_отправителя).
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let mut buf = [0; 10]; let (amt, src) = socket.recv_from(&mut buf).expect("Не удалось получить данные"); println!("Получено {} байт от {}", amt, src); }
broadcast
#![allow(unused)] fn main() { pub fn broadcast(&self) -> Result<bool> }
Получает значение параметра SO_BROADCAST для этого сокета.
Для получения дополнительной информации смотрите set_broadcast.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_broadcast(false).unwrap(); assert_eq!(socket.broadcast().unwrap(), false); }
set_broadcast
#![allow(unused)] fn main() { pub fn set_broadcast(&self, broadcast: bool) -> Result<()> }
Устанавливает значение параметра SO_BROADCAST для этого сокета.
Если установлено true, то сокет может отправлять пакеты на широковещательный адрес.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_broadcast(true).expect("Не удалось установить broadcast"); }
multicast_loop_v4
#![allow(unused)] fn main() { pub fn multicast_loop_v4(&self) -> Result<bool> }
Получает значение параметра IP_MULTICAST_LOOP для этого сокета.
Для получения дополнительной информации смотрите set_multicast_loop_v4.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_loop_v4(false).unwrap(); assert_eq!(socket.multicast_loop_v4().unwrap(), false); }
set_multicast_loop_v4
#![allow(unused)] fn main() { pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> Result<()> }
Устанавливает значение параметра IP_MULTICAST_LOOP для этого сокета.
Если установлено true, то многоадресные пакеты будут доставляться обратно в локальный сокет.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_loop_v4(true).expect("Не удалось установить multicast_loop_v4"); }
multicast_ttl_v4
#![allow(unused)] fn main() { pub fn multicast_ttl_v4(&self) -> Result<u32> }
Получает значение параметра IP_MULTICAST_TTL для этого сокета.
Для получения дополнительной информации смотрите set_multicast_ttl_v4.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_ttl_v4(1).unwrap(); assert_eq!(socket.multicast_ttl_v4().unwrap(), 1); }
set_multicast_ttl_v4
#![allow(unused)] fn main() { pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> Result<()> }
Устанавливает значение параметра IP_MULTICAST_TTL для этого сокета.
Устанавливает время жизни (TTL) для многоадресных пакетов.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_ttl_v4(1).expect("Не удалось установить multicast_ttl_v4"); }
multicast_loop_v6
#![allow(unused)] fn main() { pub fn multicast_loop_v6(&self) -> Result<bool> }
Получает значение параметра IPV6_MULTICAST_LOOP для этого сокета.
Для получения дополнительной информации смотрите set_multicast_loop_v6.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_loop_v6(false).unwrap(); assert_eq!(socket.multicast_loop_v6().unwrap(), false); }
set_multicast_loop_v6
#![allow(unused)] fn main() { pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> Result<()> }
Устанавливает значение параметра IPV6_MULTICAST_LOOP для этого сокета.
Если установлено true, то многоадресные пакеты будут доставляться обратно в локальный сокет.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_multicast_loop_v6(true).expect("Не удалось установить multicast_loop_v6"); }
ttl
#![allow(unused)] fn main() { pub fn ttl(&self) -> Result<u32> }
Получает значение параметра IP_TTL для этого сокета.
Для получения дополнительной информации смотрите set_ttl.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_ttl(100).expect("Не удалось установить TTL"); assert_eq!(socket.ttl().unwrap_or(0), 100); }
set_ttl
#![allow(unused)] fn main() { pub fn set_ttl(&self, ttl: u32) -> Result<()> }
Устанавливает значение параметра IP_TTL для этого сокета.
Этот параметр устанавливает время жизни (Time-To-Live) для пакетов, отправленных из этого сокета.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_ttl(100).expect("Не удалось установить TTL"); }
join_multicast_v4
#![allow(unused)] fn main() { pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> Result<()> }
Присоединяется к многоадресной группе IPv4.
Примеры
#![allow(unused)] fn main() { use std::net::{UdpSocket, Ipv4Addr}; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let multiaddr = Ipv4Addr::new(224, 0, 0, 1); let interface = Ipv4Addr::new(0, 0, 0, 0); socket.join_multicast_v4(&multiaddr, &interface).expect("Не удалось присоединиться к группе"); }
join_multicast_v6
#![allow(unused)] fn main() { pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> Result<()> }
Присоединяется к многоадресной группе IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{UdpSocket, Ipv6Addr}; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let multiaddr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1); socket.join_multicast_v6(&multiaddr, 0).expect("Не удалось присоединиться к группе"); }
leave_multicast_v4
#![allow(unused)] fn main() { pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> Result<()> }
Покидает многоадресную группу IPv4.
Примеры
#![allow(unused)] fn main() { use std::net::{UdpSocket, Ipv4Addr}; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let multiaddr = Ipv4Addr::new(224, 0, 0, 1); let interface = Ipv4Addr::new(0, 0, 0, 0); socket.leave_multicast_v4(&multiaddr, &interface).expect("Не удалось покинуть группу"); }
leave_multicast_v6
#![allow(unused)] fn main() { pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> Result<()> }
Покидает многоадресную группу IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{UdpSocket, Ipv6Addr}; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let multiaddr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1); socket.leave_multicast_v6(&multiaddr, 0).expect("Не удалось покинуть группу"); }
set_nonblocking
#![allow(unused)] fn main() { pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> }
Переводит сокет в неблокирующий режим.
Если nonblocking равно true, то операции над сокетом, которые блокировали бы, будут возвращать ошибки вместо блокировки. Если nonblocking равно false, то сокет будет работать в блокирующем режиме.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; use std::io; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); socket.set_nonblocking(true).expect("Не удалось установить неблокирующий режим"); let mut buf = [0; 10]; match socket.recv_from(&mut buf) { Ok((n, addr)) => println!("Получено {} байт от {}", n, addr), Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { // Данные пока не доступны } Err(e) => panic!("Неожиданная ошибка ввода-вывода: {}", e), } }
take_error
#![allow(unused)] fn main() { pub fn take_error(&self) -> Result<Option<Error>> }
Получает значение параметра сокета SO_ERROR.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); if let Ok(Some(error)) = socket.take_error() { println!("Ошибка сокета: {}", error); } }
peek
#![allow(unused)] fn main() { pub fn peek(&self, buf: &mut [u8]) -> Result<usize> }
Читает данные из сокета без удаления их из буфера.
Эта функция работает как recv, но данные, прочитанные через peek, остаются доступными для последующих вызовов recv.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let mut buf = [0; 10]; let n = socket.peek(&mut buf).expect("Ошибка peek"); println!("Просмотрено {} байт: {:?}", n, &buf[..n]); }
peek_from
#![allow(unused)] fn main() { pub fn peek_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> }
Читает данные из сокета без удаления их из буфера и возвращает адрес отправителя.
Эта функция работает как recv_from, но данные, прочитанные через peek_from, остаются доступными для последующих вызовов recv_from.
Примеры
#![allow(unused)] fn main() { use std::net::UdpSocket; let socket = UdpSocket::bind("127.0.0.1:34254").unwrap(); let mut buf = [0; 10]; let (n, addr) = socket.peek_from(&mut buf).expect("Ошибка peek_from"); println!("Просмотрено {} байт от {}: {:?}", n, addr, &buf[..n]); }
Трайт-реализации
AsFd
#![allow(unused)] fn main() { impl AsFd for UdpSocket }
Используется операционной системой для представления низкоуровневого дескриптора файла.
AsRawFd
#![allow(unused)] fn main() { impl AsRawFd for UdpSocket }
Представляет необработанный дескриптор файла.
From<UdpSocket>
#![allow(unused)] fn main() { impl From<UdpSocket> for Arc<UdpSocket> }
Преобразует UdpSocket в Arc<UdpSocket>.
From<UdpSocket>
#![allow(unused)] fn main() { impl From<UdpSocket> for Socket }
Преобразует UdpSocket в Socket.
IntoRawFd
#![allow(unused)] fn main() { impl IntoRawFd for UdpSocket }
Потребляет этот объект, возвращая необработанный дескриптор файла.
Debug
#![allow(unused)] fn main() { impl Debug for UdpSocket }
Реализует отладочное отображение для UdpSocket.
Пример использования
use std::net::UdpSocket; use std::thread; use std::time::Duration; fn main() -> std::io::Result<()> { let socket = UdpSocket::bind("127.0.0.1:0")?; // Настройка параметров сокета socket.set_broadcast(true)?; socket.set_ttl(64)?; socket.set_nonblocking(false)?; // Подключение к удаленному адресу socket.connect("127.0.0.1:8080")?; // Отправка данных socket.send(b"Hello, server!")?; // Получение ответа let mut buf = [0; 1024]; let amt = socket.recv(&mut buf)?; println!("Получен ответ: {} байт", amt); Ok(()) }
Enum
Перечисление IpAddr
#![allow(unused)] fn main() { pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), } }
IP-адрес, версия 4 или версия 6.
Этот enum может содержать либо адрес IPv4, либо адрес IPv6, с их соответствующими типами. Для представления любого IP-адреса, который может быть либо IPv4, либо IPv6, следует использовать этот тип.
Варианты
V4
#![allow(unused)] fn main() { V4(Ipv4Addr) }
Адрес IPv4.
V6
#![allow(unused)] fn main() { V6(Ipv6Addr) }
Адрес IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); assert_eq!("::1".parse(), Ok(localhost_v6)); assert_eq!(localhost_v4.is_ipv4(), true); assert_eq!(localhost_v6.is_ipv6(), true); }
Методы
is_unspecified
#![allow(unused)] fn main() { pub const fn is_unspecified(&self) -> bool }
Возвращает true, если это неспецифицированный адрес.
Для IPv4 это 0.0.0.0. Для IPv6 это ::.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); }
is_loopback
#![allow(unused)] fn main() { pub const fn is_loopback(&self) -> bool }
Возвращает true, если это адрес обратной петли.
Для IPv4 это 127.0.0.0/8. Для IPv6 это ::1.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_loopback(), true); }
is_global
#![allow(unused)] fn main() { pub fn is_global(&self) -> bool }
Возвращает true, если это глобальный адрес.
Глобальные адреса - это все адреса, которые не зарезервированы для специальных целей. Это включает в себя адреса из глобального пула unicast, а также другие адреса, которые могут быть маршрутизированы глобально.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; // Частные адреса не являются глобальными assert_eq!(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)).is_global(), false); assert_eq!(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)).is_global(), false); // Некоторые публичные адреса являются глобальными assert_eq!(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)).is_global(), true); }
is_multicast
#![allow(unused)] fn main() { pub const fn is_multicast(&self) -> bool }
Возвращает true, если это многоадресный адрес.
Для IPv4 это 224.0.0.0/4. Для IPv6 это ff00::/8.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 0, 0, 1)).is_multicast(), true); assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 1)).is_multicast(), true); }
is_ipv4
#![allow(unused)] fn main() { pub const fn is_ipv4(&self) -> bool }
Возвращает true, если это адрес IPv4.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_ipv4(), true); assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_ipv4(), false); }
is_ipv6
#![allow(unused)] fn main() { pub const fn is_ipv6(&self) -> bool }
Возвращает true, если это адрес IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_ipv6(), false); assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)).is_ipv6(), true); }
is_documentation
#![allow(unused)] fn main() { pub fn is_documentation(&self) -> bool }
Возвращает true, если это адрес, зарезервированный для документации.
Для IPv4 это 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24. Для IPv6 это 2001:db8::/32.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; assert_eq!(IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1)).is_documentation(), true); assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)).is_documentation(), true); }
to_ipv6_mapped
#![allow(unused)] fn main() { pub fn to_ipv6_mapped(&self) -> IpAddr }
Преобразует адрес IPv4 в IPv4-отображенный адрес IPv6.
Возвращает адрес IPv6, соответствующий адресу IPv4, используя механизм IPv4-отображения IPv6, определенный в IETF RFC 4291 Section 2.5.5.2.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; let ipv4 = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 255)); let ipv6_mapped = ipv4.to_ipv6_mapped(); assert_eq!( ipv6_mapped, IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)) ); }
Трайт-реализации
From<Ipv4Addr>
#![allow(unused)] fn main() { impl From<Ipv4Addr> for IpAddr }
Преобразует Ipv4Addr в IpAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr}; let addr = Ipv4Addr::new(127, 0, 0, 1); let ip_addr = IpAddr::from(addr); assert_eq!(ip_addr, IpAddr::V4(addr)); }
From<Ipv6Addr>
#![allow(unused)] fn main() { impl From<Ipv6Addr> for IpAddr }
Преобразует Ipv6Addr в IpAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv6Addr}; let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); let ip_addr = IpAddr::from(addr); assert_eq!(ip_addr, IpAddr::V6(addr)); }
Display, Debug
#![allow(unused)] fn main() { impl Display for IpAddr impl Debug for IpAddr }
Реализует отображение и отладочное отображение для IpAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr}; let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); println!("IP адрес: {}", ip); // "127.0.0.1" println!("Отладочная информация: {:?}", ip); // "V4(127.0.0.1)" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for IpAddr impl Eq for IpAddr impl PartialOrd for IpAddr impl Ord for IpAddr impl Hash for IpAddr }
Реализует сравнение и хеширование для IpAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::collections::HashMap; let ip1 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let ip2 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let ip3 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); assert_eq!(ip1, ip2); assert_ne!(ip1, ip3); let mut map = HashMap::new(); map.insert(ip1, "localhost"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for IpAddr }
Реализует парсинг из строки для IpAddr.
Примеры
#![allow(unused)] fn main() { use std::net::IpAddr; use std::str::FromStr; let ipv4 = IpAddr::from_str("192.168.1.1").unwrap(); assert!(ipv4.is_ipv4()); let ipv6 = IpAddr::from_str("::1").unwrap(); assert!(ipv6.is_ipv6()); }
Примеры использования
Проверка типов адресов
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; fn analyze_ip(ip: IpAddr) { println!("Анализ IP адреса: {}", ip); if ip.is_unspecified() { println!(" Это неспецифицированный адрес"); } if ip.is_loopback() { println!(" Это адрес обратной петли"); } if ip.is_global() { println!(" Это глобальный адрес"); } if ip.is_multicast() { println!(" Это многоадресный адрес"); } if ip.is_documentation() { println!(" Это адрес для документации"); } if ip.is_ipv4() { println!(" Это IPv4 адрес"); } if ip.is_ipv6() { println!(" Это IPv6 адрес"); } } fn main() { let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); let multicast_v4 = IpAddr::V4(Ipv4Addr::new(224, 0, 0, 1)); let documentation_v4 = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1)); analyze_ip(localhost_v4); analyze_ip(localhost_v6); analyze_ip(multicast_v4); analyze_ip(documentation_v4); }
Использование в сетевых операциях
use std::net::{TcpListener, TcpStream, IpAddr}; use std::io; fn create_server(ip: IpAddr, port: u16) -> io::Result<TcpListener> { let addr = (ip, port); TcpListener::bind(addr) } fn connect_to_server(ip: IpAddr, port: u16) -> io::Result<TcpStream> { let addr = (ip, port); TcpStream::connect(addr) } fn main() -> io::Result<()> { // Использование IPv4 let ipv4 = "127.0.0.1".parse::<IpAddr>().unwrap(); let _server_v4 = create_server(ipv4, 8080)?; // Использование IPv6 let ipv6 = "::1".parse::<IpAddr>().unwrap(); let _client_v6 = connect_to_server(ipv6, 8080)?; Ok(()) }
Фильтрация IP-адресов
use std::net::{IpAddr, Ipv4Addr}; fn filter_private_ips(ips: Vec<IpAddr>) -> Vec<IpAddr> { ips.into_iter() .filter(|ip| { if let IpAddr::V4(ipv4) = ip { // Фильтруем частные адреса IPv4 !(ipv4.octets()[0] == 10 || // 10.0.0.0/8 (ipv4.octets()[0] == 172 && ipv4.octets()[1] >= 16 && ipv4.octets()[1] <= 31) || // 172.16.0.0/12 (ipv4.octets()[0] == 192 && ipv4.octets()[1] == 168)) // 192.168.0.0/16 } else { true // Пропускаем все IPv6 адреса } }) .collect() } fn main() { let ips = vec![ "10.0.0.1".parse().unwrap(), "192.168.1.1".parse().unwrap(), "8.8.8.8".parse().unwrap(), "::1".parse().unwrap(), ]; let public_ips = filter_private_ips(ips); println!("Публичные IP адреса:"); for ip in public_ips { println!(" {}", ip); } }
Преобразование между IPv4 и IPv6
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; fn demonstrate_mapping() { let ipv4 = Ipv4Addr::new(192, 168, 1, 1); let ip_addr_v4 = IpAddr::V4(ipv4); // Преобразование в IPv4-отображенный IPv6 let ipv6_mapped = ip_addr_v4.to_ipv6_mapped(); println!("Оригинальный IPv4: {}", ipv4); println!("IPv4-отображенный IPv6: {}", ipv6_mapped); if let IpAddr::V6(ipv6) = ipv6_mapped { // Проверяем, что это действительно IPv4-отображенный адрес if ipv6.to_ipv4_mapped().is_some() { println!("Это IPv4-отображенный адрес IPv6"); } } } fn main() { demonstrate_mapping(); }
Перечисление SocketAddr
#![allow(unused)] fn main() { pub enum SocketAddr { V4(SocketAddrV4), V6(SocketAddrV6), } }
Представляет адрес интернет-сокета, либо IPv4, либо IPv6.
Варианты
V4
#![allow(unused)] fn main() { V4(SocketAddrV4) }
Адрес интернет-сокса IPv4.
V6
#![allow(unused)] fn main() { V6(SocketAddrV6) }
Адрес интернет-сокса IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); assert_eq!("[::1]:8080".parse(), Ok(socket)); }
Методы
new
#![allow(unused)] fn main() { pub const fn new(ip: IpAddr, port: u16) -> SocketAddr }
Создает новый адрес сокета из IpAddr и номера порта.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); assert_eq!(addr.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); assert_eq!(addr.port(), 8080); }
ip
#![allow(unused)] fn main() { pub const fn ip(&self) -> IpAddr }
Возвращает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); }
port
#![allow(unused)] fn main() { pub const fn port(&self) -> u16 }
Возвращает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); assert_eq!(socket.port(), 8080); }
set_ip
#![allow(unused)] fn main() { pub fn set_ip(&mut self, new_ip: IpAddr) }
Устанавливает IP-адрес, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); }
set_port
#![allow(unused)] fn main() { pub fn set_port(&mut self, new_port: u16) }
Устанавливает номер порта, связанный с этим адресом сокета.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); socket.set_port(1025); assert_eq!(socket.port(), 1025); }
is_ipv4
#![allow(unused)] fn main() { pub const fn is_ipv4(&self) -> bool }
Возвращает true, если это адрес сокета IPv4.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); assert_eq!(socket.is_ipv4(), true); assert_eq!(socket.is_ipv6(), false); }
is_ipv6
#![allow(unused)] fn main() { pub const fn is_ipv6(&self) -> bool }
Возвращает true, если это адрес сокета IPv6.
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv6Addr, SocketAddr}; let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); assert_eq!(socket.is_ipv4(), false); assert_eq!(socket.is_ipv6(), true); }
Трайт-реализации
From<SocketAddrV4>
#![allow(unused)] fn main() { impl From<SocketAddrV4> for SocketAddr }
Преобразует SocketAddrV4 в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); let socket_addr = SocketAddr::from(addr); assert_eq!(socket_addr.ip().to_string(), "127.0.0.1"); assert_eq!(socket_addr.port(), 8080); }
From<SocketAddrV6>
#![allow(unused)] fn main() { impl From<SocketAddrV6> for SocketAddr }
Преобразует SocketAddrV6 в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, SocketAddrV6, Ipv6Addr}; let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); let socket_addr = SocketAddr::from(addr); assert_eq!(socket_addr.ip().to_string(), "::1"); assert_eq!(socket_addr.port(), 8080); }
From<(IpAddr, u16)>
#![allow(unused)] fn main() { impl From<(IpAddr, u16)> for SocketAddr }
Преобразует кортеж (IpAddr, u16) в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, IpAddr, Ipv4Addr}; let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let port = 8080; let socket_addr = SocketAddr::from((ip, port)); assert_eq!(socket_addr.ip().to_string(), "127.0.0.1"); assert_eq!(socket_addr.port(), 8080); }
From<(Ipv4Addr, u16)>
#![allow(unused)] fn main() { impl From<(Ipv4Addr, u16)> for SocketAddr }
Преобразует кортеж (Ipv4Addr, u16) в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, Ipv4Addr}; let ip = Ipv4Addr::new(127, 0, 0, 1); let port = 8080; let socket_addr = SocketAddr::from((ip, port)); assert_eq!(socket_addr.ip().to_string(), "127.0.0.1"); assert_eq!(socket_addr.port(), 8080); }
From<(Ipv6Addr, u16)>
#![allow(unused)] fn main() { impl From<(Ipv6Addr, u16)> for SocketAddr }
Преобразует кортеж (Ipv6Addr, u16) в SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, Ipv6Addr}; let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); let port = 8080; let socket_addr = SocketAddr::from((ip, port)); assert_eq!(socket_addr.ip().to_string(), "::1"); assert_eq!(socket_addr.port(), 8080); }
Display, Debug
#![allow(unused)] fn main() { impl Display for SocketAddr impl Debug for SocketAddr }
Реализует отображение и отладочное отображение для SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, Ipv4Addr}; let socket = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 8080); println!("Адрес сокета: {}", socket); // "127.0.0.1:8080" println!("Отладочная информация: {:?}", socket); // "127.0.0.1:8080" }
PartialEq, Eq, PartialOrd, Ord, Hash
#![allow(unused)] fn main() { impl PartialEq for SocketAddr impl Eq for SocketAddr impl PartialOrd for SocketAddr impl Ord for SocketAddr impl Hash for SocketAddr }
Реализует сравнение и хеширование для SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, Ipv4Addr}; use std::collections::HashMap; let socket1 = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 8080); let socket2 = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 8080); let socket3 = SocketAddr::new(Ipv4Addr::new(192, 168, 0, 1).into(), 8080); assert_eq!(socket1, socket2); assert_ne!(socket1, socket3); let mut map = HashMap::new(); map.insert(socket1, "localhost"); }
FromStr
#![allow(unused)] fn main() { impl FromStr for SocketAddr }
Реализует парсинг из строки для SocketAddr.
Примеры
#![allow(unused)] fn main() { use std::net::SocketAddr; use std::str::FromStr; let socket = SocketAddr::from_str("127.0.0.1:8080").unwrap(); assert_eq!(socket.ip().to_string(), "127.0.0.1"); assert_eq!(socket.port(), 8080); let socket = SocketAddr::from_str("[::1]:8080").unwrap(); assert_eq!(socket.ip().to_string(), "::1"); assert_eq!(socket.port(), 8080); }
Примеры использования
Создание и манипуляция адресами сокетов
#![allow(unused)] fn main() { use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; // Создание адреса сокета IPv4 let ipv4_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 8080); println!("IPv4 адрес: {}", ipv4_addr); // Создание адреса сокета IPv6 let ipv6_addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)), 8080); println!("IPv6 адрес: {}", ipv6_addr); // Изменение адреса и порта let mut socket = ipv4_addr; socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))); socket.set_port(9090); println!("Измененный адрес: {}", socket); // Проверка типа адреса println!("is_ipv4: {}", socket.is_ipv4()); println!("is_ipv6: {}", socket.is_ipv6()); }
Использование в сетевых операциях
use std::net::{TcpListener, SocketAddr}; fn main() -> std::io::Result<()> { // Создание слушателя с конкретным адресом сокета let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); let listener = TcpListener::bind(addr)?; println!("Слушаем на {}", listener.local_addr()?); for stream in listener.incoming() { match stream { Ok(stream) => { let peer_addr = stream.peer_addr()?; println!("Подключение от {}", peer_addr); // Проверка типа адреса клиента if peer_addr.is_ipv6() { println!("Клиент использует IPv6"); } else { println!("Клиент использует IPv4"); } } Err(e) => eprintln!("Ошибка подключения: {}", e), } } Ok(()) }
Сравнение и хеширование
#![allow(unused)] fn main() { use std::net::SocketAddr; use std::collections::HashSet; let addr1: SocketAddr = "192.168.1.1:80".parse().unwrap(); let addr2: SocketAddr = "192.168.1.1:80".parse().unwrap(); let addr3: SocketAddr = "10.0.0.1:80".parse().unwrap(); // Сравнение assert_eq!(addr1, addr2); assert_ne!(addr1, addr3); // Использование в HashSet let mut set = HashSet::new(); set.insert(addr1); set.insert(addr2); // Не добавится, так как дубликат set.insert(addr3); println!("Количество уникальных адресов: {}", set.len()); // 2 }
Перечисление Shutdown
#![allow(unused)] fn main() { pub enum Shutdown { Read, Write, Both, } }
Флаги для отключения частей соединения.
Shutdown используется в методе shutdown для указания, какая часть соединения должна быть отключена.
Варианты
Read
#![allow(unused)] fn main() { Read }
Запрещает дальнейшие операции чтения.
После вызова shutdown(Shutdown::Read) все последующие вызовы read будут возвращать Ok(0), указывая на конец потока.
Примеры
#![allow(unused)] fn main() { use std::net::{TcpStream, Shutdown}; use std::io::Read; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); // Отключаем чтение stream.shutdown(Shutdown::Read).unwrap(); let mut buf = [0; 10]; let n = stream.read(&mut buf).unwrap(); assert_eq!(n, 0); // Больше данных для чтения нет }
Write
#![allow(unused)] fn main() { Write }
Запрещает дальнейшие операции записи.
После вызова shutdown(Shutdown::Write) все последующие вызовы write будут возвращать ошибку.
Примеры
#![allow(unused)] fn main() { use std::net::{TcpStream, Shutdown}; use std::io::Write; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); // Отключаем запись stream.shutdown(Shutdown::Write).unwrap(); // Попытка записи после отключения match stream.write(b"hello") { Ok(_) => println!("Запись успешна"), Err(e) => println!("Ошибка записи: {}", e), // Будет ошибка } }
Both
#![allow(unused)] fn main() { Both }
Запрещает как чтение, так и запись.
Эквивалентно вызову shutdown(Shutdown::Read) и shutdown(Shutdown::Write).
Примеры
#![allow(unused)] fn main() { use std::net::{TcpStream, Shutdown}; use std::io::{Read, Write}; let stream = TcpStream::connect("127.0.0.1:8080").unwrap(); // Полностью отключаем соединение stream.shutdown(Shutdown::Both).unwrap(); // И чтение, и запись теперь будут возвращать ошибки let mut buf = [0; 10]; let read_result = stream.read(&mut buf); let write_result = stream.write(b"hello"); println!("Чтение после отключения: {:?}", read_result); println!("Запись после отключения: {:?}", write_result); }
Трайт-реализации
Clone, Copy
#![allow(unused)] fn main() { impl Clone for Shutdown impl Copy for Shutdown }
Реализует клонирование и копирование для Shutdown.
Примеры
#![allow(unused)] fn main() { use std::net::Shutdown; let shutdown_read = Shutdown::Read; let shutdown_read_clone = shutdown_read.clone(); // Клонирование let shutdown_read_copy = shutdown_read; // Копирование assert_eq!(shutdown_read, shutdown_read_clone); assert_eq!(shutdown_read, shutdown_read_copy); }
Debug
#![allow(unused)] fn main() { impl Debug for Shutdown }
Реализует отладочное отображение для Shutdown.
Примеры
#![allow(unused)] fn main() { use std::net::Shutdown; println!("Отладочная информация: {:?}", Shutdown::Read); // "Read" println!("Отладочная информация: {:?}", Shutdown::Write); // "Write" println!("Отладочная информация: {:?}", Shutdown::Both); // "Both" }
PartialEq, Eq
#![allow(unused)] fn main() { impl PartialEq for Shutdown impl Eq for Shutdown }
Реализует сравнение для Shutdown.
Примеры
#![allow(unused)] fn main() { use std::net::Shutdown; assert_eq!(Shutdown::Read, Shutdown::Read); assert_ne!(Shutdown::Read, Shutdown::Write); assert_eq!(Shutdown::Both, Shutdown::Both); }
Примеры использования
Базовое использование с TCP соединениями
use std::net::{TcpStream, Shutdown}; use std::io::{Read, Write}; use std::thread; use std::time::Duration; fn demonstrate_shutdown() -> std::io::Result<()> { // Предположим, что у нас есть TCP соединение let stream = TcpStream::connect("127.0.0.1:8080")?; println!("Демонстрация Shutdown::Read:"); stream.shutdown(Shutdown::Read)?; let mut buf = [0; 1024]; match stream.read(&mut buf) { Ok(0) => println!(" ✓ Чтение возвращает 0 (конец потока)"), Ok(n) => println!(" ✗ Неожиданно прочитано {} байт", n), Err(e) => println!(" ✗ Ошибка чтения: {}", e), } // Создаем новое соединение для следующего теста let stream2 = TcpStream::connect("127.0.0.1:8080")?; println!("\nДемонстрация Shutdown::Write:"); stream2.shutdown(Shutdown::Write)?; match stream2.write(b"Hello, server!") { Ok(_) => println!(" ✗ Запись неожиданно удалась"), Err(e) => println!(" ✓ Запись возвращает ошибку: {}", e), } // Создаем новое соединение для следующего теста let stream3 = TcpStream::connect("127.0.0.1:8080")?; println!("\nДемонстрация Shutdown::Both:"); stream3.shutdown(Shutdown::Both)?; let read_result = stream3.read(&mut buf); let write_result = stream3.write(b"Hello"); println!(" Чтение после Both: {:?}", read_result); println!(" Запись после Both: {:?}", write_result); Ok(()) } fn main() -> std::io::Result<()> { demonstrate_shutdown() }
Грациозное завершение сервера
use std::net::{TcpListener, TcpStream, Shutdown}; use std::io::{Read, Write}; use std::thread; use std::sync::{Arc, Mutex}; use std::time::Duration; struct ConnectionManager { active_connections: Mutex<Vec<TcpStream>>, } impl ConnectionManager { fn new() -> Self { Self { active_connections: Mutex::new(Vec::new()), } } fn add_connection(&self, stream: TcpStream) { let mut connections = self.active_connections.lock().unwrap(); connections.push(stream); } fn graceful_shutdown(&self) -> std::io::Result<()> { let mut connections = self.active_connections.lock().unwrap(); println!("Начинаем грациозное завершение {} соединений...", connections.len()); for (i, stream) in connections.iter_mut().enumerate() { println!(" Завершаем соединение {}", i + 1); // Сначала отключаем запись - уведомляем клиент о завершении if let Err(e) = stream.shutdown(Shutdown::Write) { println!(" Предупреждение: не удалось отключить запись: {}", e); } // Даем клиенту время завершить свою работу thread::sleep(Duration::from_millis(100)); // Затем полностью закрываем соединение if let Err(e) = stream.shutdown(Shutdown::Both) { println!(" Предупреждение: не удалось полностью отключить: {}", e); } } connections.clear(); println!("Все соединения завершены грациозно."); Ok(()) } } fn handle_client(stream: TcpStream, manager: Arc<ConnectionManager>) { manager.add_connection(stream); // Имитация обработки клиента println!("Обработка нового клиента..."); thread::sleep(Duration::from_secs(5)); println!("Обработка клиента завершена."); } fn main() -> std::io::Result<()> { let manager = Arc::new(ConnectionManager::new()); let listener = TcpListener::bind("127.0.0.1:0")?; let port = listener.local_addr()?.port(); println!("Сервер запущен на порту {}", port); // Запускаем сервер в отдельном потоке let manager_clone = Arc::clone(&manager); let server_handle = thread::spawn(move || { for stream_result in listener.incoming().take(3) { // Принимаем только 3 соединения match stream_result { Ok(stream) => { let manager = Arc::clone(&manager_clone); thread::spawn(move || { handle_client(stream, manager); }); } Err(e) => eprintln!("Ошибка принятия соединения: {}", e), } } }); // Даем серверу время принять соединения thread::sleep(Duration::from_secs(2)); // Грациозное завершение println!("\nИнициируем грациозное завершение..."); manager.graceful_shutdown()?; server_handle.join().unwrap(); println!("Сервер завершил работу."); Ok(()) }
Двусторонняя коммуникация с контролируемым завершением
use std::net::{TcpStream, Shutdown}; use std::io::{Read, Write}; use std::thread; use std::time::Duration; fn client_with_controlled_shutdown() -> std::io::Result<()> { let mut stream = TcpStream::connect("127.0.0.1:8080")?; // Фаза 1: Нормальная коммуникация println!("Фаза 1: Нормальная коммуникация"); stream.write_all(b"Hello from client")?; let mut buffer = [0; 1024]; let n = stream.read(&mut buffer)?; println!("Получено от сервера: {}", String::from_utf8_lossy(&buffer[..n])); // Фаза 2: Отключаем только запись (уведомляем сервер о завершении отправки) println!("\nФаза 2: Отключаем запись (Shutdown::Write)"); stream.shutdown(Shutdown::Write)?; // Можем еще читать ответы от сервера match stream.read(&mut buffer) { Ok(0) => println!("Сервер закрыл соединение"), Ok(n) => println!("Финальное сообщение от сервера: {}", String::from_utf8_lossy(&buffer[..n])), Err(e) => println!("Ошибка чтения: {}", e), } // Фаза 3: Полное закрытие println!("\nФаза 3: Полное закрытие (Shutdown::Both)"); stream.shutdown(Shutdown::Both)?; println!("Соединение полностью закрыто"); Ok(()) } fn simulate_server() -> std::io::Result<()> { let listener = std::net::TcpListener::bind("127.0.0.1:8080")?; thread::spawn(move || { for stream in listener.incoming() { match stream { Ok(mut stream) => { thread::spawn(move || { let mut buffer = [0; 1024]; // Читаем запрос от клиента match stream.read(&mut buffer) { Ok(0) => { println!("Клиент закрыл соединение"); return; } Ok(n) => { println!("Сервер получил: {}", String::from_utf8_lossy(&buffer[..n])); // Отправляем ответ stream.write_all(b"Hello from server").unwrap(); // Ждем, пока клиент отключит запись thread::sleep(Duration::from_secs(1)); // Отправляем финальное сообщение stream.write_all(b"Final message from server").unwrap(); // Грациозно закрываем соединение stream.shutdown(Shutdown::Both).unwrap(); } Err(e) => { eprintln!("Ошибка чтения: {}", e); } } }); } Err(e) => eprintln!("Ошибка принятия соединения: {}", e), } } }); Ok(()) } fn main() -> std::io::Result<()> { // Запускаем имитацию сервера simulate_server()?; // Даем серверу время запуститься thread::sleep(Duration::from_millis(100)); // Запускаем клиента client_with_controlled_shutdown()?; Ok(()) }
Обработка ошибок при отключении
use std::net::{TcpStream, Shutdown}; use std::io; fn demonstrate_shutdown_errors() { let test_cases = [ ("Нормальное соединение", || { TcpStream::connect("127.0.0.1:8080") }), ("Уже закрытое соединение", || { let stream = TcpStream::connect("127.0.0.1:8080")?; stream.shutdown(Shutdown::Both)?; Ok(stream) }), ]; for (description, stream_creator) in test_cases { println!("Тест: {}", description); match stream_creator() { Ok(stream) => { // Пытаемся отключить разными способами let results = [ ("Shutdown::Read", stream.shutdown(Shutdown::Read)), ("Shutdown::Write", stream.shutdown(Shutdown::Write)), ("Shutdown::Both", stream.shutdown(Shutdown::Both)), ]; for (shutdown_type, result) in results { match result { Ok(()) => println!(" ✓ {}: успешно", shutdown_type), Err(e) => println!(" ✗ {}: ошибка - {}", shutdown_type, e), } } } Err(e) => { println!(" ✗ Не удалось создать соединение: {}", e); } } println!(); } } fn main() { demonstrate_shutdown_errors(); }
Использование в протоколе с подтверждением завершения
use std::net::{TcpStream, Shutdown}; use std::io::{Read, Write}; use std::time::{Duration, Instant}; struct GracefulProtocol; impl GracefulProtocol { fn perform_graceful_shutdown(mut stream: TcpStream) -> std::io::Result<()> { println!("Начинаем грациозное завершение протокола..."); // Шаг 1: Отправляем уведомление о завершении println!("Шаг 1: Отправляем FINISH команду"); stream.write_all(b"FINISH")?; // Шаг 2: Ждем подтверждения от другой стороны println!("Шаг 2: Ждем подтверждения ACK"); let mut buffer = [0; 3]; let start = Instant::now(); let timeout = Duration::from_secs(5); while start.elapsed() < timeout { match stream.read(&mut buffer) { Ok(0) => { println!(" Соединение закрыто другой стороной"); break; } Ok(n) if &buffer[..n] == b"ACK" => { println!(" ✓ Получено подтверждение ACK"); break; } Ok(n) => { println!(" Получен неожиданный ответ: {}", String::from_utf8_lossy(&buffer[..n])); } Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { // Продолжаем ждать continue; } Err(e) => { println!(" Ошибка чтения: {}", e); break; } } } // Шаг 3: Отключаем запись println!("Шаг 3: Отключаем запись (Shutdown::Write)"); stream.shutdown(Shutdown::Write)?; // Шаг 4: Ждем, пока другая сторона тоже отключит запись println!("Шаг 4: Ждем завершения другой стороны"); thread::sleep(Duration::from_secs(1)); // Шаг 5: Полное закрытие println!("Шаг 5: Полное закрытие (Shutdown::Both)"); stream.shutdown(Shutdown::Both)?; println!("Грациозное завершение завершено успешно"); Ok(()) } } fn main() -> std::io::Result<()> { // В реальном приложении здесь было бы установлено соединение println!("Демонстрация протокола грациозного завершения"); println!("(В реальном приложении здесь было бы реальное соединение)"); Ok(()) }
Особенности использования
Поведение на разных платформах
- Unix-подобные системы: использует системный вызов
shutdown() - Windows: использует
shutdown()из Winsock API
Множественные вызовы
Многократные вызовы shutdown() с одинаковым или разными флагами допустимы, но могут возвращать ошибки если соединение уже закрыто.
Взаимодействие с закрытием
shutdown() отличается от простого закрытия (close()) сокета:
shutdown()уведомляет другую сторону о завершении определенной операцииclose()освобождает ресурсы, но может не уведомлять другую сторону немедленно
Использование с неблокирующими сокетами
Поведение shutdown() с неблокирующими сокетами такое же, как и с блокирующими.
Перечисление Ipv6MulticastScope
#![allow(unused)] fn main() { #[non_exhaustive] pub enum Ipv6MulticastScope { InterfaceLocal, LinkLocal, RealmLocal, AdminLocal, SiteLocal, OrganizationLocal, Global, } }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия IPv6 многоадресного адреса, как определено в IETF RFC 7346, раздел 2.
Гарантии стабильности
Не все возможные значения для многоадресной области были назначены. Будущие RFC могут вводить новые области, которые будут добавлены как варианты в это перечисление; из-за этого перечисление помечено как #[non_exhaustive].
Примеры
#![allow(unused)] #![feature(ip)] fn main() { use std::net::Ipv6Addr; use std::net::Ipv6MulticastScope::*; // IPv6 многоадресный адрес с глобальной областью действия (`ff0e::`). let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0); // Напечатает "Global scope". match address.multicast_scope() { Some(InterfaceLocal) => println!("Interface-Local scope"), Some(LinkLocal) => println!("Link-Local scope"), Some(RealmLocal) => println!("Realm-Local scope"), Some(AdminLocal) => println!("Admin-Local scope"), Some(SiteLocal) => println!("Site-Local scope"), Some(OrganizationLocal) => println!("Organization-Local scope"), Some(Global) => println!("Global scope"), Some(_) => println!("Unknown scope"), None => println!("Not a multicast address!") } }
Варианты (Не исчерпывающие)
Это перечисление помечено как не исчерпывающее
InterfaceLocal
#![allow(unused)] fn main() { InterfaceLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия в пределах интерфейса.
LinkLocal
#![allow(unused)] fn main() { LinkLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия в пределах канала (link).
RealmLocal
#![allow(unused)] fn main() { RealmLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия в пределах REALM.
AdminLocal
#![allow(unused)] fn main() { AdminLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Административно-локальная область действия.
SiteLocal
#![allow(unused)] fn main() { SiteLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия в пределах сайта.
OrganizationLocal
#![allow(unused)] fn main() { OrganizationLocal }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Область действия в пределах организации.
Global
#![allow(unused)] fn main() { Global }
🔬 Это экспериментальное API, доступное только в ночных сборках. (ip #27709)
Глобальная область действия.
Трайт-реализации
Clone для Ipv6MulticastScope
#![allow(unused)] fn main() { impl Clone for Ipv6MulticastScope }
clone
#![allow(unused)] fn main() { fn clone(&self) -> Ipv6MulticastScope }
Возвращает дубликат значения. Подробнее
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет присваивание копированием из источника. Подробнее
Debug для Ipv6MulticastScope
#![allow(unused)] fn main() { impl Debug for Ipv6MulticastScope }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматировщика. Подробнее
Hash для Ipv6MulticastScope
#![allow(unused)] fn main() { impl Hash for Ipv6MulticastScope }
hash
#![allow(unused)] fn main() { fn hash<__H>(&self, state: &mut __H) where __H: Hasher, }
Подает это значение в заданный Hasher. Подробнее
hash_slice
#![allow(unused)] fn main() { fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher, Self: Sized, }
Подает срез этого типа в заданный Hasher. Подробнее
PartialEq для Ipv6MulticastScope
#![allow(unused)] fn main() { impl PartialEq for Ipv6MulticastScope }
eq
#![allow(unused)] fn main() { fn eq(&self, other: &Ipv6MulticastScope) -> bool }
Проверяет равенство значений self и other, используется оператором ==.
ne
#![allow(unused)] fn main() { fn ne(&self, other: &Rhs) -> bool }
Проверяет неравенство (!=). Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины.
Copy для Ipv6MulticastScope
#![allow(unused)] fn main() { impl Copy for Ipv6MulticastScope }
Eq для Ipv6MulticastScope
#![allow(unused)] fn main() { impl Eq for Ipv6MulticastScope }
StructuralPartialEq для Ipv6MulticastScope
#![allow(unused)] fn main() { impl StructuralPartialEq for Ipv6MulticastScope }
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl Freeze for Ipv6MulticastScope impl RefUnwindSafe for Ipv6MulticastScope impl Send for Ipv6MulticastScope impl Sync for Ipv6MulticastScope impl Unpin for Ipv6MulticastScope impl UnwindSafe for Ipv6MulticastScope }
Стандартные реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, impl<T> Borrow<T> for T where T: ?Sized, impl<T> BorrowMut<T> for T where T: ?Sized, impl<T> CloneToUninit for T where T: Clone, impl<T> From<T> for T impl<T, U> Into<U> for T where U: From<T>, impl<T> ToOwned for T where T: Clone, impl<T, U> TryFrom<U> for T where U: Into<T>, impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Примеры использования
Анализ многоадресных областей IPv6
#![feature(ip)] use std::net::{Ipv6Addr, Ipv6MulticastScope}; fn analyze_multicast_addresses() { let multicast_addresses = [ // Различные многоадресные адреса с разными областями Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0x1), // Interface-Local Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1), // Link-Local Ipv6Addr::new(0xff03, 0, 0, 0, 0, 0, 0, 0x1), // Realm-Local Ipv6Addr::new(0xff04, 0, 0, 0, 0, 0, 0, 0x1), // Admin-Local Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 0, 0x1), // Site-Local Ipv6Addr::new(0xff08, 0, 0, 0, 0, 0, 0, 0x1), // Organization-Local Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0x1), // Global ]; println!("Анализ IPv6 многоадресных областей:"); for addr in &multicast_addresses { print!("Адрес: {:39} -> ", addr); match addr.multicast_scope() { Some(Ipv6MulticastScope::InterfaceLocal) => { println!("Interface-Local (в пределах интерфейса)"); } Some(Ipv6MulticastScope::LinkLocal) => { println!("Link-Local (в пределах канала)"); } Some(Ipv6MulticastScope::RealmLocal) => { println!("Realm-Local (в пределах REALM)"); } Some(Ipv6MulticastScope::AdminLocal) => { println!("Admin-Local (административно-локальная)"); } Some(Ipv6MulticastScope::SiteLocal) => { println!("Site-Local (в пределах сайта)"); } Some(Ipv6MulticastScope::OrganizationLocal) => { println!("Organization-Local (в пределах организации)"); } Some(Ipv6MulticastScope::Global) => { println!("Global (глобальная)"); } Some(_) => { println!("Неизвестная область"); } None => { println!("Не многоадресный адрес"); } } } } fn main() { analyze_multicast_addresses(); }
Использование в сетевых приложениях
#![feature(ip)] use std::net::{Ipv6Addr, Ipv6MulticastScope}; use std::collections::HashMap; struct MulticastManager { scopes: HashMap<Ipv6MulticastScope, Vec<Ipv6Addr>>, } impl MulticastManager { fn new() -> Self { Self { scopes: HashMap::new(), } } fn add_multicast_address(&mut self, addr: Ipv6Addr) { if let Some(scope) = addr.multicast_scope() { self.scopes.entry(scope).or_insert_with(Vec::new).push(addr); } } fn print_scopes(&self) { println!("Многоадресные адреса по областям:"); for (scope, addresses) in &self.scopes { let scope_name = match scope { Ipv6MulticastScope::InterfaceLocal => "Interface-Local", Ipv6MulticastScope::LinkLocal => "Link-Local", Ipv6MulticastScope::RealmLocal => "Realm-Local", Ipv6MulticastScope::AdminLocal => "Admin-Local", Ipv6MulticastScope::SiteLocal => "Site-Local", Ipv6MulticastScope::OrganizationLocal => "Organization-Local", Ipv6MulticastScope::Global => "Global", }; println!(" {} ({} адресов):", scope_name, addresses.len()); for addr in addresses { println!(" - {}", addr); } } } fn get_addresses_by_scope(&self, scope: Ipv6MulticastScope) -> &[Ipv6Addr] { self.scopes.get(&scope).map(|v| v.as_slice()).unwrap_or(&[]) } } fn main() { let mut manager = MulticastManager::new(); // Добавляем различные многоадресные адреса let multicast_addrs = [ Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0x1), // all-nodes interface-local Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0x1), // all-nodes link-local Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0x2), // all-routers link-local Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 0, 0x1), // all-nodes site-local Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0x1), // global multicast ]; for addr in &multicast_addrs { manager.add_multicast_address(*addr); } manager.print_scopes(); // Получаем адреса для конкретной области println!("\nLink-Local адреса:"); for addr in manager.get_addresses_by_scope(Ipv6MulticastScope::LinkLocal) { println!(" - {}", addr); } }
Сравнение и хеширование областей
#![feature(ip)] use std::net::Ipv6MulticastScope; use std::collections::HashSet; fn demonstrate_comparison_and_hashing() { let scopes = [ Ipv6MulticastScope::InterfaceLocal, Ipv6MulticastScope::LinkLocal, Ipv6MulticastScope::RealmLocal, Ipv6MulticastScope::AdminLocal, Ipv6MulticastScope::SiteLocal, Ipv6MulticastScope::OrganizationLocal, Ipv6MulticastScope::Global, Ipv6MulticastScope::LinkLocal, // Дубликат ]; println!("Демонстрация сравнения и хеширования:"); // Использование в HashSet (автоматически удаляет дубликаты) let unique_scopes: HashSet<_> = scopes.iter().collect(); println!("Уникальные области в HashSet: {}", unique_scopes.len()); for scope in &unique_scopes { println!(" - {:?}", scope); } // Сравнение областей println!("\nСравнение областей:"); let scope1 = Ipv6MulticastScope::LinkLocal; let scope2 = Ipv6MulticastScope::LinkLocal; let scope3 = Ipv6MulticastScope::Global; println!(" scope1 == scope2: {}", scope1 == scope2); println!(" scope1 == scope3: {}", scope1 == scope3); println!(" scope1 != scope3: {}", scope1 != scope3); // Клонирование и копирование println!("\nКлонирование и копирование:"); let original = Ipv6MulticastScope::SiteLocal; let cloned = original.clone(); let copied = original; println!(" original: {:?}", original); println!(" cloned: {:?}", cloned); println!(" copied: {:?}", copied); println!(" original == cloned: {}", original == cloned); println!(" original == copied: {}", original == copied); } fn main() { demonstrate_comparison_and_hashing(); }
Области многоадресной рассылки IPv6
Области многоадресной рассылки определяют, как далеко могут распространяться многоадресные пакеты:
- Interface-Local: В пределах одного сетевого интерфейса
- Link-Local: В пределах одного сетевого сегмента (link)
- Realm-Local: В пределах REALM (определяется спецификацией)
- Admin-Local: Административно ограниченная область
- Site-Local: В пределах одного сайта или здания
- Organization-Local: В пределах одной организации
- Global: Глобальная область действия (вся сеть Интернет)
Особенности использования
Не исчерпывающее перечисление
Перечисление помечено как #[non_exhaustive], что означает, что в будущем могут быть добавлены новые варианты. Это требует от пользователей обрабатывать возможные неизвестные варианты при использовании сопоставления с образцом.
Экспериментальный статус
Это API является экспериментальным и доступно только в ночных сборках Rust. Для использования необходимо включить функцию #![feature(ip)].
Трайт ToSocketAddrs
#![allow(unused)] fn main() { pub trait ToSocketAddrs { type Iter: Iterator<Item = SocketAddr>; fn to_socket_addrs(&self) -> Result<Self::Iter>; } }
Трайт для объектов, которые могут быть преобразованы в SocketAddr.
Этот трайт используется для обобщенного разрешения адресов в объекты SocketAddr. По умолчанию он реализован для следующих типов:
SocketAddr-to_socket_addrsявляется тождественной функциейSocketAddrV4,SocketAddrV6- преобразуются вSocketAddr- (
IpAddr,u16) - создает адрес сокета из IP-адреса и порта - (
Ipv4Addr,u16), (Ipv6Addr,u16) - аналогично предыдущему &str- строка в формате"host:port"или"host"(с портом по умолчанию 0)&String- то же самое, что и&str&[SocketAddr]- итератор по уже разрешенным адресам
Обязательные ассоциированные типы
Iter
#![allow(unused)] fn main() { type Iter: Iterator<Item = SocketAddr> }
Возвращаемый итератор по адресам сокетов, который может создавать несколько значений SocketAddr из одного входного значения.
Обязательные методы
to_socket_addrs
#![allow(unused)] fn main() { fn to_socket_addrs(&self) -> Result<Self::Iter> }
Преобразует объект в итератор по разрешенным SocketAddr.
Возвращаемый итератор может не возвращать адреса в определенном порядке. Порт по умолчанию - 0.
Реализации по умолчанию
Для SocketAddr
#![allow(unused)] fn main() { impl ToSocketAddrs for SocketAddr { type Iter = option::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> Result<option::IntoIter<SocketAddr>> { Ok(Some(*self).into_iter()) } } }
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, ToSocketAddrs}; let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); for socket_addr in addr.to_socket_addrs().unwrap() { println!("Адрес: {}", socket_addr); } }
Для &[SocketAddr]
#![allow(unused)] fn main() { impl<'a> ToSocketAddrs for &'a [SocketAddr] { type Iter = iter::Cloned<slice::Iter<'a, SocketAddr>>; fn to_socket_addrs(&self) -> Result<iter::Cloned<slice::Iter<'a, SocketAddr>>> { Ok(self.iter().cloned()) } } }
Примеры
#![allow(unused)] fn main() { use std::net::{SocketAddr, ToSocketAddrs}; let addrs = [ "127.0.0.1:8080".parse().unwrap(), "127.0.0.1:8081".parse().unwrap(), ]; for socket_addr in addrs.to_socket_addrs().unwrap() { println!("Адрес: {}", socket_addr); } }
Для кортежа (IpAddr, u16)
#![allow(unused)] fn main() { impl ToSocketAddrs for (IpAddr, u16) { type Iter = option::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> Result<option::IntoIter<SocketAddr>> { let (ip, port) = *self; Ok(Some(SocketAddr::new(ip, port)).into_iter()) } } }
Примеры
#![allow(unused)] fn main() { use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs}; let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let port = 8080; for socket_addr in (ip, port).to_socket_addrs().unwrap() { println!("Адрес: {}", socket_addr); } }
Для строк &str и String
#![allow(unused)] fn main() { impl ToSocketAddrs for &str { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> Result<vec::IntoIter<SocketAddr>> { // Реализация разрешения имен хостов } } impl ToSocketAddrs for String { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> Result<vec::IntoIter<SocketAddr>> { (&**self).to_socket_addrs() } } }
Примеры
#![allow(unused)] fn main() { use std::net::ToSocketAddrs; // Разрешение IPv4 адреса for socket_addr in "127.0.0.1:8080".to_socket_addrs().unwrap() { println!("IPv4 адрес: {}", socket_addr); } // Разрешение IPv6 адреса for socket_addr in "[::1]:8080".to_socket_addrs().unwrap() { println!("IPv6 адрес: {}", socket_addr); } // Разрешение имени хоста if let Ok(addrs) = "example.com:80".to_socket_addrs() { for socket_addr in addrs { println!("Адрес хоста: {}", socket_addr); } } // Только порт (localhost с портом 0) for socket_addr in ":0".to_socket_addrs().unwrap() { println!("Адрес: {}", socket_addr); } }
Примеры использования
Использование в сетевых функциях
use std::net::{TcpStream, TcpListener, UdpSocket}; use std::io; fn connect_to_server<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { TcpStream::connect(addr) } fn create_listener<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { TcpListener::bind(addr) } fn create_udp_socket<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> { UdpSocket::bind(addr) } fn main() -> io::Result<()> { // Различные способы указания адресов let _stream1 = connect_to_server("127.0.0.1:8080")?; let _stream2 = connect_to_server(("127.0.0.1".parse().unwrap(), 8080))?; let _stream3 = connect_to_server("[::1]:8080")?; let _listener = create_listener("0.0.0.0:8080")?; let _udp_socket = create_udp_socket("localhost:0")?; Ok(()) }
Обработка множественных адресов
use std::net::{TcpStream, ToSocketAddrs}; use std::io; fn try_connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { let mut last_error = None; for socket_addr in addr.to_socket_addrs()? { match TcpStream::connect(socket_addr) { Ok(stream) => return Ok(stream), Err(e) => last_error = Some(e), } } Err(last_error.unwrap_or_else(|| { io::Error::new(io::ErrorKind::Other, "не удалось разрешить адрес") })) } fn main() -> io::Result<()> { // Попытка подключения к нескольким адресам let stream = try_connect("example.com:80")?; println!("Успешно подключились!"); Ok(()) }
Создание пользовательских типов, реализующих ToSocketAddrs
use std::net::{SocketAddr, ToSocketAddrs}; use std::vec; #[derive(Debug)] struct ServerConfig { host: String, port: u16, backup_ports: Vec<u16>, } impl ToSocketAddrs for ServerConfig { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> std::io::Result<vec::IntoIter<SocketAddr>> { let mut addrs = Vec::new(); // Основной порт let main_addr = format!("{}:{}", self.host, self.port); addrs.extend(main_addr.to_socket_addrs()?); // Резервные порты for &port in &self.backup_ports { let backup_addr = format!("{}:{}", self.host, port); addrs.extend(backup_addr.to_socket_addrs()?); } Ok(addrs.into_iter()) } } fn main() -> std::io::Result<()> { let config = ServerConfig { host: "localhost".to_string(), port: 8080, backup_ports: vec![8081, 8082], }; println!("Доступные адреса сервера:"); for addr in config.to_socket_addrs()? { println!(" {}", addr); } Ok(()) }
Использование с UDP сокетами
use std::net::{UdpSocket, ToSocketAddrs}; use std::io; fn send_message<A: ToSocketAddrs>(socket: &UdpSocket, msg: &[u8], addr: A) -> io::Result<usize> { let mut last_error = None; for target_addr in addr.to_socket_addrs()? { match socket.send_to(msg, target_addr) { Ok(size) => return Ok(size), Err(e) => last_error = Some(e), } } Err(last_error.unwrap_or_else(|| { io::Error::new(io::ErrorKind::Other, "не удалось отправить на любой адрес") })) } fn main() -> io::Result<()> { let socket = UdpSocket::bind("0.0.0.0:0")?; // Отправка на различные типы адресов send_message(&socket, b"Hello", "127.0.0.1:8080")?; send_message(&socket, b"Hello", ("::1".parse().unwrap(), 8080))?; send_message(&socket, b"Hello", "localhost:8080")?; Ok(()) }
Особенности реализации
Разрешение имен хостов
При использовании строк для разрешения адресов:
- Блокирующая операция: разрешение имен хостов может блокировать текущий поток
- Множественные адреса: один хост может вернуть несколько IP-адресов
- Порядок: адреса могут возвращаться в произвольном порядке
- Таймауты: разрешение имен подвержено таймаутам сети
Порт по умолчанию
Когда порт не указан (например, "localhost"), используется порт 0.
Ошибки разрешения
Метод возвращает io::Result, который может содержать ошибки:
io::ErrorKind::InvalidInput- неверный формат адресаio::ErrorKind::Other- ошибки разрешения именio::ErrorKind::TimedOut- таймаут разрешения
Рекомендации по использованию
- Всегда обрабатывайте ошибки - разрешение адресов может завершиться неудачно
- Итерируйтесь по результатам - один вызов может вернуть несколько адресов
- Используйте для гибкости - принимайте
ToSocketAddrsв своих API - Помните о блокировках - разрешение имен хостов блокирует поток
Модуль str
Утилиты для примитивного типа str.
Смотри также: примитивный тип str.
Модули
pattern (Экспериментальный)
API для работы со строковыми шаблонами (Pattern).
Структуры
| Имя структуры | Описание |
|---|---|
| Bytes | Итератор по байтам среза строки. |
| CharIndices | Итератор по символам (char) среза строки вместе с их позициями. |
| Chars | Итератор по символам (char) среза строки. |
| EncodeUtf16 | Итератор по значениям u16, представляющим строку в кодировке UTF-16. |
| EscapeDebug | Тип, возвращаемый методом str::escape_debug. |
| EscapeDefault | Тип, возвращаемый методом str::escape_default. |
| EscapeUnicode | Тип, возвращаемый методом str::escape_unicode. |
| Lines | Итератор по строкам текста (линиям) в виде срезов строк. |
| LinesAny (Устарел) | Создается методом lines_any. |
| MatchIndices | Создается методом match_indices. |
| Matches | Создается методом matches. |
| ParseBoolError | Ошибка, возвращаемая при неудачном парсинге значения bool с помощью from_str. |
| RMatchIndices | Создается методом rmatch_indices. |
| RMatches | Создается методом rmatches. |
| RSplit | Создается методом rsplit. |
| RSplitN | Создается методом rsplitn. |
| RSplitTerminator | Создается методом rsplit_terminator. |
| Split | Создается методом split. |
| SplitAsciiWhitespace | Итератор по подстрокам, разделенным произвольным количеством ASCII-пробелов. Возвращает подстроки, не являющиеся ASCII-пробелами. |
| SplitInclusive | Итератор по подстрокам, завершающимся подстрокой, соответствующей предикату. В отличие от Split, включает совпадающую часть как терминатор подстроки. |
| SplitN | Создается методом splitn. |
| SplitTerminator | Создается методом split_terminator. |
| SplitWhitespace | Итератор по подстрокам, разделенным произвольным количеством пробелов. Возвращает подстроки, не являющиеся пробелами. |
| Utf8Chunk | Элемент, возвращаемый итератором Utf8Chunks. |
| Utf8Chunks | Итератор для декодирования среза байтов (в основном UTF-8) в срезы строк (&str) и срезы байтов (&[u8]). |
| Utf8Error | Ошибки, которые могут возникнуть при попытке интерпретировать последовательность байтов u8 как строку. |
Трейты
FromStr
Парсинг значения из строки.
Функции
| Имя функции | Статус | Описание |
|---|---|---|
| from_boxed_utf8_unchecked | ⚠️ (небезопасная) | Преобразует упакованный срез байтов (Box<[u8]>) в упакованный срез строки (Box<str>) без проверки корректности UTF-8. |
| from_utf8 | - | Преобразует срез байтов (&[u8]) в срез строки (&str). |
| from_utf8_mut | - | Преобразует изменяемый срез байтов (&mut [u8]) в изменяемый срез строки (&mut str). |
| from_utf8_unchecked | ⚠️ (небезопасная) | Преобразует срез байтов (&[u8]) в срез строки (&str) без проверки корректности UTF-8. |
| from_utf8_unchecked_mut | ⚠️ (небезопасная) | Преобразует срез байтов (&[u8]) в срез строки (&str) без проверки корректности UTF-8; изменяемая версия. |
| from_raw_parts | ⚠️ (экспериментальная) | Создает &str из указателя и длины. |
| from_raw_parts_mut | ⚠️ (экспериментальная) | Создает &mut str из указателя и длины. |
Модуль pattern
🔬 Это экспериментальное API, доступное только в ночных сборках. (pattern #27721)
API для работы со строковыми шаблонами (Pattern).
API Pattern предоставляет обобщенный механизм для использования различных типов шаблонов при поиске в строке.
Для получения более подробной информации см. трейты Pattern, Searcher, ReverseSearcher и DoubleEndedSearcher.
Хотя это API является нестабильным, оно доступно через стабильные API типа str.
Примеры
Pattern реализован в стабильном API для &str, char, срезов char, а также для функций и замыканий, реализующих FnMut(char) -> bool.
#![allow(unused)] fn main() { let s = "Can you find a needle in a haystack?"; // Шаблон типа &str assert_eq!(s.find("you"), Some(4)); // Шаблон типа char assert_eq!(s.find('n'), Some(2)); // Шаблон в виде массива символов assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u']), Some(1)); // Шаблон в виде среза символов assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1)); // Шаблон в виде замыкания assert_eq!(s.find(|c: char| c.is_ascii_punctuation()), Some(35)); }
Структуры
| Имя структуры | Описание |
|---|---|
| CharArrayRefSearcher (Экспериментальный) | Ассоциированный тип для <&[char; N] as Pattern>::Searcher<'a>. |
| CharArraySearcher (Экспериментальный) | Ассоциированный тип для <[char; N] as Pattern>::Searcher<'a>. |
| CharPredicateSearcher (Экспериментальный) | Ассоциированный тип для <F as Pattern>::Searcher<'a>. |
| CharSearcher (Экспериментальный) | Ассоциированный тип для <char as Pattern>::Searcher<'a>. |
| CharSliceSearcher (Экспериментальный) | Ассоциированный тип для <&[char] as Pattern>::Searcher<'a>. |
| StrSearcher (Экспериментальный) | Ассоциированный тип для <&str as Pattern>::Searcher<'a>. |
Перечисления (Enums)
| Имя перечисления | Описание |
|---|---|
| SearchStep (Экспериментальный) | Результат вызова Searcher::next() или ReverseSearcher::next_back(). |
| Utf8Pattern (Экспериментальный) | Результат вызова Pattern::as_utf8_pattern(). Может использоваться для проверки содержимого шаблона в случаях, когда внутреннее представление может быть выражено в UTF-8. |
Трейты
| Имя трейта | Описание |
|---|---|
| DoubleEndedSearcher (Экспериментальный) | Маркерный трейт, указывающий, что ReverseSearcher может использоваться для реализации DoubleEndedIterator. |
| Pattern (Экспериментальный) | Строковый шаблон. |
| ReverseSearcher (Экспериментальный) | Обратный поисковик для строкового шаблона. |
| Searcher (Экспериментальный) | Поисковик для строкового шаблона. |
Struct
Структура Bytes
#![allow(unused)] fn main() { pub struct Bytes<'a>(/* приватные поля */); }
Итератор по байтам среза строки.
Эта структура создается методом bytes для типа str. Подробнее см. в его документации.
Реализации трейтов
impl<'a> Clone for Bytes<'a>
fn clone
#![allow(unused)] fn main() { fn clone(&self) -> Bytes<'a> ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет копирующее присваивание из source.
impl<'a> Debug for Bytes<'a>
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl DoubleEndedIterator for Bytes<'_>
next_back
#![allow(unused)] fn main() { fn next_back(&mut self) -> Option<u8> }
Удаляет и возвращает элемент с конца итератора.
nth_back
#![allow(unused)] fn main() { fn nth_back(&mut self, n: usize) -> Option<<Bytes<'_> as Iterator>::Item> }
Возвращает n-й элемент с конца итератора.
rfind
#![allow(unused)] fn main() { fn rfind<P>(&mut self, predicate: P) -> Option<<Bytes<'_> as Iterator>::Item> where P: FnMut(&<Bytes<'_> as Iterator>::Item) -> bool, }
Ищет элемент итератора с конца, удовлетворяющий предикату.
advance_back_by
#![allow(unused)] fn main() { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор с конца на n элементов.
try_rfold
#![allow(unused)] fn main() { fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Обратная версия Iterator::try_fold(): берет элементы, начиная с конца итератора.
rfold
#![allow(unused)] fn main() { fn rfold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Метод итератора, который сводит элементы итератора к единственному конечному значению, начиная с конца.
impl ExactSizeIterator for Bytes<'_>
len
#![allow(unused)] fn main() { fn len(&self) -> usize }
Возвращает точное оставшееся количество элементов итератора.
is_empty
#![allow(unused)] fn main() { fn is_empty(&self) -> bool }
🔬 Это экспериментальное API, доступное только в ночных сборках. (exact_size_is_empty #35428)
Возвращает true, если итератор пуст.
impl Iterator for Bytes<'_>
Item
#![allow(unused)] fn main() { type Item = u8 }
Тип элементов, по которым выполняется итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<u8> }
Перемещает итератор и возвращает следующее значение.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
count
#![allow(unused)] fn main() { fn count(self) -> usize }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
last
#![allow(unused)] fn main() { fn last(self) -> Option<<Bytes<'_> as Iterator>::Item> }
Потребляет итератор, возвращая последний элемент.
nth
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<<Bytes<'_> as Iterator>::Item> }
Возвращает n-й элемент итератора.
all
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where F: FnMut(<Bytes<'_> as Iterator>::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where F: FnMut(<Bytes<'_> as Iterator>::Item) -> bool, }
Проверяет, соответствует ли хотя бы один элемент итератора предикату.
find
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<<Bytes<'_> as Iterator>::Item> where P: FnMut(&<Bytes<'_> as Iterator>::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
position
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(<Bytes<'_> as Iterator>::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(<Bytes<'_> as Iterator>::Item) -> bool, }
Ищет элемент в итераторе справа, возвращая его индекс.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326) Перемещает итератор и возвращает массив, содержащий следующие N значений.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор на n элементов.
step_by
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом заданного размера на каждой итерации.
chain
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение.
peekable
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления. Подробнее см. в их документации.
skip_while
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует их.
skip
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше.
scan
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но сглаживает вложенную структуру.
flatten
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который сглаживает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого непрерывного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются.
fuse
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который завершается после первого None.
inspect
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Выполняет действие с каждым элементом итератора, передавая значение дальше.
by_ref
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для данного экземпляра Iterator.
collect
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047) Преобразует итератор в коллекцию с обработкой ошибок, прерываясь при первой неудаче.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780) Собирает все элементы из итератора в коллекцию.
partition
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборлах. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом так, чтобы все элементы, возвращающие true, предшествовали всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_fold
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию, пока она возвращает успех, производя единственное конечное значение.
try_for_each
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу итератора, останавливаясь при первой ошибке и возвращая эту ошибку.
fold
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Складывает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
reduce
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному путем многократного применения операции сокращения.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053) Сводит элементы к одному путем многократного применения операции сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
find_map
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178) Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
max
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения.
min_by_key
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения.
rev
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Изменяет направление итератора на противоположное.
unzip
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450) Возвращает итератор по N элементов итератора за раз.
sum
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы.
cmp
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше элементы этого Iterator, чем элементы другого.
le
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше или равны элементы этого Iterator элементам другого.
gt
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше элементы этого Iterator, чем элементы другого.
ge
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше или равны элементы этого Iterator элементам другого.
is_sorted
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции сравнения.
is_sorted_by_key
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl FusedIterator for Bytes<'_>
impl TrustedLen for Bytes<'_>
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for Bytes<'a> impl<'a> RefUnwindSafe for Bytes<'a> impl<'a> Send for Bytes<'a> impl<'a> Sync for Bytes<'a> impl<'a> Unpin for Bytes<'a> impl<'a> UnwindSafe for Bytes<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Структура CharIndices
#![allow(unused)] fn main() { pub struct CharIndices<'a> { /* приватные поля */ } }
Итератор по символам (char) среза строки вместе с их позициями.
Эта структура создается методом char_indices для типа str. Подробнее см. в его документации.
Методы
impl<'a> CharIndices<'a>
as_str (с версии 1.4.0)
#![allow(unused)] fn main() { pub fn as_str(&self) -> &'a str }
Возвращает представление базовых данных как под-срез исходных данных.
Имеет то же время жизни, что и исходный срез, поэтому итератор можно продолжать использовать, пока этот срез существует.
offset (с версии 1.82.0)
#![allow(unused)] fn main() { pub fn offset(&self) -> usize }
Возвращает позицию в байтах следующего символа или длину базовой строки, если больше нет символов.
Это означает, что когда итератор еще не полностью потреблен, возвращаемое значение будет соответствовать индексу, который будет возвращен следующим вызовом next().
Примеры
#![allow(unused)] fn main() { let mut chars = "a楽".char_indices(); // `next()` еще не вызывался, поэтому `offset()` возвращает байтовый // индекс первого символа строки, который всегда равен 0. assert_eq!(chars.offset(), 0); // Как и ожидалось, первый вызов `next()` также возвращает 0 как индекс. assert_eq!(chars.next(), Some((0, 'a'))); // `next()` был вызван один раз, поэтому `offset()` возвращает байтовый индекс // второго символа ... assert_eq!(chars.offset(), 1); // ... который соответствует индексу, возвращаемому следующим вызовом `next()`. assert_eq!(chars.next(), Some((1, '楽'))); // Как только итератор будет потреблен, `offset()` возвращает длину // строки в байтах. assert_eq!(chars.offset(), 4); assert_eq!(chars.next(), None); }
Реализации трейтов
impl<'a> Clone for CharIndices<'a>
clone
#![allow(unused)] fn main() { fn clone(&self) -> CharIndices<'a> ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет копирующее присваивание из source.
impl<'a> Debug for CharIndices<'a>
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl<'a> DoubleEndedIterator for CharIndices<'a>
next_back
#![allow(unused)] fn main() { fn next_back(&mut self) -> Option<(usize, char)> }
Удаляет и возвращает элемент с конца итератора.
advance_back_by
#![allow(unused)] fn main() { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор с конца на n элементов.
nth_back (с версии 1.37.0)
#![allow(unused)] fn main() { fn nth_back(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент с конца итератора.
try_rfold (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Обратная версия Iterator::try_fold(): берет элементы, начиная с конца итератора.
rfold (с версии 1.27.0)
#![allow(unused)] fn main() { fn rfold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Метод итератора, который сводит элементы итератора к единственному конечному значению, начиная с конца.
rfind (с версии 1.27.0)
#![allow(unused)] fn main() { fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора с конца, удовлетворяющий предикату.
impl<'a> Iterator for CharIndices<'a>
type Item
#![allow(unused)] fn main() { type Item = (usize, char) }
Тип элементов, по которым выполняется итерация (пара: индекс и символ).
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<(usize, char)> }
Перемещает итератор и возвращает следующее значение.
count
#![allow(unused)] fn main() { fn count(self) -> usize }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
last
#![allow(unused)] fn main() { fn last(self) -> Option<(usize, char)> }
Потребляет итератор, возвращая последний элемент.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326) Перемещает итератор и возвращает массив, содержащий следующие N значений.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор на n элементов.
nth
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора.
step_by (с версии 1.28.0)
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом заданного размера на каждой итерации.
chain (с версии 1.0.0)
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip (с версии 1.0.0)
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map (с версии 1.0.0)
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each (с версии 1.21.0)
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate (с версии 1.0.0)
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение.
peekable (с версии 1.0.0)
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления.
skip_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while (с версии 1.57.0)
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует их.
skip (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take (с версии 1.0.0)
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше.
scan (с версии 1.0.0)
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но сглаживает вложенную структуру.
flatten (с версии 1.29.0)
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который сглаживает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого непрерывного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются.
fuse (с версии 1.0.0)
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который завершается после первого None.
inspect (с версии 1.0.0)
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Выполняет действие с каждым элементом итератора, передавая значение дальше.
by_ref (с версии 1.0.0)
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для данного экземпляра Iterator.
collect (с версии 1.0.0)
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047) Преобразует итератор в коллекцию с обработкой ошибок, прерываясь при первой неудаче.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780) Собирает все элементы из итератора в коллекцию.
partition (с версии 1.0.0)
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом так, чтобы все элементы, возвращающие true, предшествовали всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_fold (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию, пока она возвращает успех, производя единственное конечное значение.
try_for_each (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу итератора, останавливаясь при первой ошибке и возвращая эту ошибку.
fold (с версии 1.0.0)
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Складывает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
reduce (с версии 1.51.0)
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному путем многократного применения операции сокращения.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053) Сводит элементы к одному путем многократного применения операции сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
all (с версии 1.0.0)
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any (с версии 1.0.0)
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли хотя бы один элемент итератора предикату.
find (с версии 1.0.0)
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
find_map (с версии 1.30.0)
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178) Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
position (с версии 1.0.0)
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition (с версии 1.0.0)
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator, }
Ищет элемент в итераторе справа, возвращая его индекс.
max (с версии 1.0.0)
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min (с версии 1.0.0)
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения.
min_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения.
rev (с версии 1.0.0)
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Изменяет направление итератора на противоположное.
unzip (с версии 1.0.0)
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied (с версии 1.36.0)
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned (с версии 1.0.0)
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle (с версии 1.0.0)
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450) Возвращает итератор по N элементов итератора за раз.
sum (с версии 1.11.0)
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product (с версии 1.11.0)
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы.
cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq (с версии 1.5.0)
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne (с версии 1.5.0)
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt (с версии 1.5.0)
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше элементы этого Iterator, чем элементы другого.
le (с версии 1.5.0)
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше или равны элементы этого Iterator элементам другого.
gt (с версии 1.5.0)
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше элементы этого Iterator, чем элементы другого.
ge (с версии 1.5.0)
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше или равны элементы этого Iterator элементам другого.
is_sorted (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции сравнения.
is_sorted_by_key (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl FusedIterator for CharIndices<'_> (с версии 1.26.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for CharIndices<'a> impl<'a> RefUnwindSafe for CharIndices<'a> impl<'a> Send for CharIndices<'a> impl<'a> Sync for CharIndices<'a> impl<'a> Unpin for CharIndices<'a> impl<'a> UnwindSafe for CharIndices<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Структура Chars
#![allow(unused)] fn main() { pub struct Chars<'a> { /* приватные поля */ } }
Итератор по символам (char) среза строки.
Эта структура создается методом chars для типа str. Подробнее см. в его документации.
Методы
impl<'a> Chars<'a>
as_str (с версии 1.4.0)
#![allow(unused)] fn main() { pub fn as_str(&self) -> &'a str }
Возвращает представление базовых данных как под-срез исходных данных.
Имеет то же время жизни, что и исходный срез, поэтому итератор можно продолжать использовать, пока этот срез существует.
Примеры
#![allow(unused)] fn main() { let mut chars = "abc".chars(); assert_eq!(chars.as_str(), "abc"); chars.next(); assert_eq!(chars.as_str(), "bc"); chars.next(); chars.next(); assert_eq!(chars.as_str(), ""); }
Реализации трейтов
impl<'a> Clone for Chars<'a>
clone
#![allow(unused)] fn main() { fn clone(&self) -> Chars<'a> ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет копирующее присваивание из source.
impl Debug for Chars<'_> (с версии 1.38.0)
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl<'a> DoubleEndedIterator for Chars<'a>
next_back
#![allow(unused)] fn main() { fn next_back(&mut self) -> Option<char> }
Удаляет и возвращает элемент с конца итератора.
advance_back_by
#![allow(unused)] fn main() { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор с конца на n элементов.
nth_back (с версии 1.37.0)
#![allow(unused)] fn main() { fn nth_back(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент с конца итератора.
try_rfold (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Обратная версия Iterator::try_fold(): берет элементы, начиная с конца итератора.
rfold (с версии 1.27.0)
#![allow(unused)] fn main() { fn rfold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Метод итератора, который сводит элементы итератора к единственному конечному значению, начиная с конца.
rfind (с версии 1.27.0)
#![allow(unused)] fn main() { fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора с конца, удовлетворяющий предикату.
impl<'a> Iterator for Chars<'a>
type Item
#![allow(unused)] fn main() { type Item = char }
Тип элементов, по которым выполняется итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<char> }
Перемещает итератор и возвращает следующее значение.
count
#![allow(unused)] fn main() { fn count(self) -> usize }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, remainder: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор на n элементов.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
last
#![allow(unused)] fn main() { fn last(self) -> Option<char> }
Потребляет итератор, возвращая последний элемент.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326) Перемещает итератор и возвращает массив, содержащий следующие N значений.
nth (с версии 1.0.0)
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора.
step_by (с версии 1.28.0)
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом заданного размера на каждой итерации.
chain (с версии 1.0.0)
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip (с версии 1.0.0)
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map (с версии 1.0.0)
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each (с версии 1.21.0)
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate (с версии 1.0.0)
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение.
peekable (с версии 1.0.0)
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления.
skip_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while (с версии 1.57.0)
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует их.
skip (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take (с версии 1.0.0)
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше.
scan (с версии 1.0.0)
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но сглаживает вложенную структуру.
flatten (с версии 1.29.0)
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который сглаживает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого непрерывного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются.
fuse (с версии 1.0.0)
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который завершается после первого None.
inspect (с версии 1.0.0)
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Выполняет действие с каждым элементом итератора, передавая значение дальше.
by_ref (с версии 1.0.0)
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для данного экземпляра Iterator.
collect (с версии 1.0.0)
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047) Преобразует итератор в коллекцию с обработкой ошибок, прерываясь при первой неудаче.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780) Собирает все элементы из итератора в коллекцию.
partition (с версии 1.0.0)
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом так, чтобы все элементы, возвращающие true, предшествовали всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_fold (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию, пока она возвращает успех, производя единственное конечное значение.
try_for_each (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу итератора, останавливаясь при первой ошибке и возвращая эту ошибку.
fold (с версии 1.0.0)
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Складывает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
reduce (с версии 1.51.0)
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному путем многократного применения операции сокращения.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053) Сводит элементы к одному путем многократного применения операции сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
all (с версии 1.0.0)
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any (с версии 1.0.0)
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли хотя бы один элемент итератора предикату.
find (с версии 1.0.0)
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
find_map (с версии 1.30.0)
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178) Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
position (с версии 1.0.0)
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition (с версии 1.0.0)
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator, }
Ищет элемент в итераторе справа, возвращая его индекс.
max (с версии 1.0.0)
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min (с версии 1.0.0)
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения.
min_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения.
rev (с версии 1.0.0)
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Изменяет направление итератора на противоположное.
unzip (с версии 1.0.0)
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied (с версии 1.36.0)
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned (с версии 1.0.0)
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle (с версии 1.0.0)
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450) Возвращает итератор по N элементов итератора за раз.
sum (с версии 1.11.0)
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product (с версии 1.11.0)
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы.
cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq (с версии 1.5.0)
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne (с версии 1.5.0)
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt (с версии 1.5.0)
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше элементы этого Iterator, чем элементы другого.
le (с версии 1.5.0)
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше или равны элементы этого Iterator элементам другого.
gt (с версии 1.5.0)
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше элементы этого Iterator, чем элементы другого.
ge (с версии 1.5.0)
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше или равны элементы этого Iterator элементам другого.
is_sorted (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции сравнения.
is_sorted_by_key (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl FusedIterator for Chars<'_> (с версии 1.26.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for Chars<'a> impl<'a> RefUnwindSafe for Chars<'a> impl<'a> Send for Chars<'a> impl<'a> Sync for Chars<'a> impl<'a> Unpin for Chars<'a> impl<'a> UnwindSafe for Chars<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Структура EncodeUtf16
#![allow(unused)] fn main() { pub struct EncodeUtf16<'a> { /* приватные поля */ } }
Итератор по значениям u16, представляющим строку в кодировке UTF-16.
Эта структура создается методом encode_utf16 для типа str. Подробнее см. в его документации.
Реализации трейтов
impl<'a> Clone for EncodeUtf16<'a>
clone
#![allow(unused)] fn main() { fn clone(&self) -> EncodeUtf16<'a> ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет копирующее присваивание из source.
impl Debug for EncodeUtf16<'_> (с версии 1.17.0)
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl<'a> Iterator for EncodeUtf16<'a>
type Item
#![allow(unused)] fn main() { type Item = u16 }
Тип элементов, по которым выполняется итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<u16> }
Перемещает итератор и возвращает следующее значение.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326) Перемещает итератор и возвращает массив, содержащий следующие N значений.
count (с версии 1.0.0)
#![allow(unused)] fn main() { fn count(self) -> usize where Self: Sized, }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
last (с версии 1.0.0)
#![allow(unused)] fn main() { fn last(self) -> Option<Self::Item> where Self: Sized, }
Потребляет итератор, возвращая последний элемент.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор на n элементов.
nth (с версии 1.0.0)
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора.
step_by (с версии 1.28.0)
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом заданного размера на каждой итерации.
chain (с версии 1.0.0)
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip (с версии 1.0.0)
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map (с версии 1.0.0)
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each (с версии 1.21.0)
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate (с версии 1.0.0)
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение.
peekable (с версии 1.0.0)
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления.
skip_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while (с версии 1.57.0)
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует их.
skip (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take (с версии 1.0.0)
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше.
scan (с версии 1.0.0)
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но сглаживает вложенную структуру.
flatten (с версии 1.29.0)
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который сглаживает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого непрерывного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются.
fuse (с версии 1.0.0)
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который завершается после первого None.
inspect (с версии 1.0.0)
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Выполняет действие с каждым элементом итератора, передавая значение дальше.
by_ref (с версии 1.0.0)
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для данного экземпляра Iterator.
collect (с версии 1.0.0)
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047) Преобразует итератор в коллекцию с обработкой ошибок, прерываясь при первой неудаче.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780) Собирает все элементы из итератора в коллекцию.
partition (с версии 1.0.0)
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом так, чтобы все элементы, возвращающие true, предшествовали всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_fold (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию, пока она возвращает успех, производя единственное конечное значение.
try_for_each (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу итератора, останавливаясь при первой ошибке и возвращая эту ошибку.
fold (с версии 1.0.0)
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Складывает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
reduce (с версии 1.51.0)
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному путем многократного применения операции сокращения.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053) Сводит элементы к одному путем многократного применения операции сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
all (с версии 1.0.0)
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any (с версии 1.0.0)
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли хотя бы один элемент итератора предикату.
find (с версии 1.0.0)
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
find_map (с версии 1.30.0)
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178) Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
position (с версии 1.0.0)
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition (с версии 1.0.0)
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator, }
Ищет элемент в итераторе справа, возвращая его индекс.
max (с версии 1.0.0)
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min (с версии 1.0.0)
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения.
min_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения.
rev (с версии 1.0.0)
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Изменяет направление итератора на противоположное.
unzip (с версии 1.0.0)
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied (с версии 1.36.0)
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned (с версии 1.0.0)
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle (с версии 1.0.0)
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450) Возвращает итератор по N элементов итератора за раз.
sum (с версии 1.11.0)
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product (с версии 1.11.0)
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы.
cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq (с версии 1.5.0)
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne (с версии 1.5.0)
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt (с версии 1.5.0)
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше элементы этого Iterator, чем элементы другого.
le (с версии 1.5.0)
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше или равны элементы этого Iterator элементам другого.
gt (с версии 1.5.0)
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше элементы этого Iterator, чем элементы другого.
ge (с версии 1.5.0)
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше или равны элементы этого Iterator элементам другого.
is_sorted (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции сравнения.
is_sorted_by_key (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl FusedIterator for EncodeUtf16<'_> (с версии 1.26.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for EncodeUtf16<'a> impl<'a> RefUnwindSafe for EncodeUtf16<'a> impl<'a> Send for EncodeUtf16<'a> impl<'a> Sync for EncodeUtf16<'a> impl<'a> Unpin for EncodeUtf16<'a> impl<'a> UnwindSafe for EncodeUtf16<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Структура EscapeDebug
#![allow(unused)] fn main() { pub struct EscapeDebug<'a> { /* приватные поля */ } }
Тип, возвращаемый методом str::escape_debug.
Реализации трейтов
impl<'a> Clone for EscapeDebug<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> EscapeDebug<'a> ⓘ | let cloned = escape_debug.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | escape_debug.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a> Debug for EscapeDebug<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", escape_debug); | Форматирует значение с помощью заданного форматтера |
impl<'a> Display for EscapeDebug<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{}", escape_debug); | Форматирует значение с помощью заданного форматтера |
impl<'a> Iterator for EscapeDebug<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| type Item | type Item = char | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<char> | let next_char = escape_debug.next(); | Перемещает итератор и возвращает следующее значение |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let hint = escape_debug.size_hint(); | Возвращает границы оставшейся длины итератора |
| try_fold | fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R | `let sum = escape_debug.try_fold(0, | acc, c |
| fold | fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc | `let sum = escape_debug.fold(0, | acc, c |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = escape_debug.next_chunk::<3>()?; | 🔬 Возвращает массив, содержащий следующие N значений |
| count | fn count(self) -> usize | let total = escape_debug.count(); | Подсчитывает количество итераций и возвращает его |
| last | fn last(self) -> Option<Self::Item> | let last_char = escape_debug.last(); | Возвращает последний элемент итератора |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | escape_debug.advance_by(3)?; | 🔬 Перемещает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = escape_debug.nth(2); | Возвращает n-й элемент итератора |
| step_by | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = escape_debug.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let combined = escape_debug.chain(other_chars); | Объединяет два итератора в последовательный |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let zipped = escape_debug.zip(other_chars); | "Объединяет" два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_spaces = escape_debug.intersperse(' '); | 🔬 Помещает копию separator между элементами |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = escape_debug.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let uppercased = escape_debug.map( | c |
| for_each | fn for_each<F>(self, f: F) | `escape_debug.for_each( | c |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let filtered = escape_debug.filter( | c |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let digits = escape_debug.filter_map( | c |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, c) in escape_debug.enumerate() { ... } | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = escape_debug.peekable(); | Создает итератор с возможностью просмотра следующего элемента |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = escape_debug.skip_while( | c |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = escape_debug.take_while( | c |
| map_while | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = escape_debug.map_while( | c |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = escape_debug.skip(3); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = escape_debug.take(5); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = escape_debug.scan(0, | state, c |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let flattened = escape_debug.flat_map( | c |
| flatten | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = escape_debug.flatten(); | Сглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = escape_debug.map_windows::<_, _, 2>( | arr |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = escape_debug.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = escape_debug.inspect( | c |
| by_ref | fn by_ref(&mut self) -> &mut Self | let part = escape_debug.by_ref().take(5).collect::<String>(); | Создает адаптер "по ссылке" для итератора |
| collect | fn collect<B>(self) -> B | let string: String = escape_debug.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<String, _> = escape_debug.try_collect(); | 🔬 Преобразует итератор в коллекцию с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | let mut s = String::new(); escape_debug.collect_into(&mut s); | 🔬 Собирает все элементы в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (letters, digits): (String, String) = escape_debug.partition( | c |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let count = escape_debug.partition_in_place( | c |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = escape_debug.is_partitioned( | c |
| try_for_each | fn try_for_each<F, R>(&mut self, f: F) -> R | `let result: Result<(), _> = escape_debug.try_for_each( | c |
| reduce | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let max_char = escape_debug.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let result: Result<Option | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_letters = escape_debug.all( | c |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_digit = escape_debug.any( | c |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_digit = escape_debug.find( | c |
| find_map | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let digit_value = escape_debug.find_map( | c |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result: Result<Option | c |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = escape_debug.position( | c |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let pos = escape_debug.rposition( | c |
| max | fn max(self) -> Option<Self::Item> | let max_char = escape_debug.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let min_char = escape_debug.min(); | Возвращает минимальный элемент |
| max_by_key | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let max = escape_debug.max_by_key( | c |
| max_by | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let max = escape_debug.max_by( | a, b |
| min_by_key | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let min = escape_debug.min_by_key( | c |
| min_by | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let min = escape_debug.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = escape_debug.rev(); | Изменяет направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (chars, bytes): (Vec | c |
| copied | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied_chars = escape_debug.copied(); | Создает итератор, который копирует все элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned_chars = escape_debug.cloned(); | Создает итератор, который клонирует все элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = escape_debug.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | for chunk in escape_debug.array_chunks::<3>() { ... } | 🔬 Возвращает итератор по N элементов за раз |
| sum | fn sum<S>(self) -> S | `let total: u32 = escape_debug.map( | c |
| product | fn product<P>(self) -> P | `let product: u32 = escape_debug.map( | c |
| cmp | fn cmp<I>(self, other: I) -> Ordering | let ordering = escape_debug.cmp(other_chars); | Лексикографически сравнивает элементы с другими |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = escape_debug.cmp_by(other_chars, | a, b |
| partial_cmp | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = escape_debug.partial_cmp(other_chars); | Частично сравнивает элементы с другими |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = escape_debug.partial_cmp_by(other_chars, | a, b |
| eq | fn eq<I>(self, other: I) -> bool | let equal = escape_debug.eq(other_chars); | Проверяет равенство элементов с другими |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = escape_debug.eq_by(other_chars, | a, b |
| ne | fn ne<I>(self, other: I) -> bool | let not_equal = escape_debug.ne(other_chars); | Проверяет неравенство элементов с другими |
| lt | fn lt<I>(self, other: I) -> bool | let less = escape_debug.lt(other_chars); | Проверяет, меньше ли элементы, чем другие |
| le | fn le<I>(self, other: I) -> bool | let less_or_equal = escape_debug.le(other_chars); | Проверяет, меньше или равны ли элементы |
| gt | fn gt<I>(self, other: I) -> bool | let greater = escape_debug.gt(other_chars); | Проверяет, больше ли элементы, чем другие |
| ge | fn ge<I>(self, other: I) -> bool | let greater_or_equal = escape_debug.ge(other_chars); | Проверяет, больше или равны ли элементы |
| is_sorted | fn is_sorted(self) -> bool | let sorted = escape_debug.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = escape_debug.is_sorted_by( | a, b |
| is_sorted_by_key | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = escape_debug.is_sorted_by_key( | c |
impl<'a> FusedIterator for EscapeDebug<'a> (с версии 1.34.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for EscapeDebug<'a> impl<'a> RefUnwindSafe for EscapeDebug<'a> impl<'a> Send for EscapeDebug<'a> impl<'a> Sync for EscapeDebug<'a> impl<'a> Unpin for EscapeDebug<'a> impl<'a> UnwindSafe for EscapeDebug<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> ToString for T where T: Display + ?Sized, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Обозначения:
- 🔬 - экспериментальное API, доступное только в ночных сборках
ⓘ- обозначение, что функция возвращает итератор
Структура EscapeDefault
#![allow(unused)] fn main() { pub struct EscapeDefault<'a> { /* приватные поля */ } }
Тип, возвращаемый методом str::escape_default.
Реализации трейтов
impl<'a> Clone for EscapeDefault<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> EscapeDefault<'a> ⓘ | let cloned = escape_default.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | escape_default.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a> Debug for EscapeDefault<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", escape_default); | Форматирует значение с помощью заданного форматтера |
impl<'a> Display for EscapeDefault<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{}", escape_default); | Форматирует значение с помощью заданного форматтера |
impl<'a> Iterator for EscapeDefault<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| type Item | type Item = char | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<char> | let next_char = escape_default.next(); | Перемещает итератор и возвращает следующее значение |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let hint = escape_default.size_hint(); | Возвращает границы оставшейся длины итератора |
| try_fold | fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R | `let sum = escape_default.try_fold(0, | acc, c |
| fold | fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc | `let sum = escape_default.fold(0, | acc, c |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = escape_default.next_chunk::<3>()?; | 🔬 Возвращает массив, содержащий следующие N значений |
| count | fn count(self) -> usize | let total = escape_default.count(); | Подсчитывает количество итераций и возвращает его |
| last | fn last(self) -> Option<Self::Item> | let last_char = escape_default.last(); | Возвращает последний элемент итератора |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | escape_default.advance_by(3)?; | 🔬 Перемещает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = escape_default.nth(2); | Возвращает n-й элемент итератора |
| step_by | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = escape_default.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let combined = escape_default.chain(other_chars); | Объединяет два итератора в последовательный |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let zipped = escape_default.zip(other_chars); | "Объединяет" два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_spaces = escape_default.intersperse(' '); | 🔬 Помещает копию separator между элементами |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = escape_default.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let uppercased = escape_default.map( | c |
| for_each | fn for_each<F>(self, f: F) | `escape_default.for_each( | c |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let filtered = escape_default.filter( | c |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let digits = escape_default.filter_map( | c |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, c) in escape_default.enumerate() { ... } | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = escape_default.peekable(); | Создает итератор с возможностью просмотра следующего элемента |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = escape_default.skip_while( | c |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = escape_default.take_while( | c |
| map_while | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = escape_default.map_while( | c |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = escape_default.skip(3); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = escape_default.take(5); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = escape_default.scan(0, | state, c |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let flattened = escape_default.flat_map( | c |
| flatten | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = escape_default.flatten(); | Сглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = escape_default.map_windows::<_, _, 2>( | arr |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = escape_default.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = escape_default.inspect( | c |
| by_ref | fn by_ref(&mut self) -> &mut Self | let part = escape_default.by_ref().take(5).collect::<String>(); | Создает адаптер "по ссылке" для итератора |
| collect | fn collect<B>(self) -> B | let string: String = escape_default.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<String, _> = escape_default.try_collect(); | 🔬 Преобразует итератор в коллекцию с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | let mut s = String::new(); escape_default.collect_into(&mut s); | 🔬 Собирает все элементы в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (letters, digits): (String, String) = escape_default.partition( | c |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let count = escape_default.partition_in_place( | c |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = escape_default.is_partitioned( | c |
| try_for_each | fn try_for_each<F, R>(&mut self, f: F) -> R | `let result: Result<(), _> = escape_default.try_for_each( | c |
| reduce | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let max_char = escape_default.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let result: Result<Option | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_letters = escape_default.all( | c |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_digit = escape_default.any( | c |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_digit = escape_default.find( | c |
| find_map | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let digit_value = escape_default.find_map( | c |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result: Result<Option | c |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = escape_default.position( | c |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let pos = escape_default.rposition( | c |
| max | fn max(self) -> Option<Self::Item> | let max_char = escape_default.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let min_char = escape_default.min(); | Возвращает минимальный элемент |
| max_by_key | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let max = escape_default.max_by_key( | c |
| max_by | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let max = escape_default.max_by( | a, b |
| min_by_key | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let min = escape_default.min_by_key( | c |
| min_by | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let min = escape_default.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = escape_default.rev(); | Изменяет направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (chars, bytes): (Vec | c |
| copied | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied_chars = escape_default.copied(); | Создает итератор, который копирует все элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned_chars = escape_default.cloned(); | Создает итератор, который клонирует все элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = escape_default.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | for chunk in escape_default.array_chunks::<3>() { ... } | 🔬 Возвращает итератор по N элементов за раз |
| sum | fn sum<S>(self) -> S | `let total: u32 = escape_default.map( | c |
| product | fn product<P>(self) -> P | `let product: u32 = escape_default.map( | c |
| cmp | fn cmp<I>(self, other: I) -> Ordering | let ordering = escape_default.cmp(other_chars); | Лексикографически сравнивает элементы с другими |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = escape_default.cmp_by(other_chars, | a, b |
| partial_cmp | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = escape_default.partial_cmp(other_chars); | Частично сравнивает элементы с другими |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = escape_default.partial_cmp_by(other_chars, | a, b |
| eq | fn eq<I>(self, other: I) -> bool | let equal = escape_default.eq(other_chars); | Проверяет равенство элементов с другими |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = escape_default.eq_by(other_chars, | a, b |
| ne | fn ne<I>(self, other: I) -> bool | let not_equal = escape_default.ne(other_chars); | Проверяет неравенство элементов с другими |
| lt | fn lt<I>(self, other: I) -> bool | let less = escape_default.lt(other_chars); | Проверяет, меньше ли элементы, чем другие |
| le | fn le<I>(self, other: I) -> bool | let less_or_equal = escape_default.le(other_chars); | Проверяет, меньше или равны ли элементы |
| gt | fn gt<I>(self, other: I) -> bool | let greater = escape_default.gt(other_chars); | Проверяет, больше ли элементы, чем другие |
| ge | fn ge<I>(self, other: I) -> bool | let greater_or_equal = escape_default.ge(other_chars); | Проверяет, больше или равны ли элементы |
| is_sorted | fn is_sorted(self) -> bool | let sorted = escape_default.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = escape_default.is_sorted_by( | a, b |
| is_sorted_by_key | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = escape_default.is_sorted_by_key( | c |
impl<'a> FusedIterator for EscapeDefault<'a> (с версии 1.34.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for EscapeDefault<'a> impl<'a> RefUnwindSafe for EscapeDefault<'a> impl<'a> Send for EscapeDefault<'a> impl<'a> Sync for EscapeDefault<'a> impl<'a> Unpin for EscapeDefault<'a> impl<'a> UnwindSafe for EscapeDefault<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> ToString for T where T: Display + ?Sized, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Обозначения:
- 🔬 - экспериментальное API, доступное только в ночных сборках
ⓘ- обозначение, что функция возвращает итератор
Структура EscapeUnicode
#![allow(unused)] fn main() { pub struct EscapeUnicode<'a> { /* приватные поля */ } }
Тип, возвращаемый методом str::escape_unicode.
Реализации трейтов
impl<'a> Clone for EscapeUnicode<'a>
clone
#![allow(unused)] fn main() { fn clone(&self) -> EscapeUnicode<'a> ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет копирующее присваивание из source.
impl<'a> Debug for EscapeUnicode<'a>
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl<'a> Display for EscapeUnicode<'a>
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматтера.
impl<'a> Iterator for EscapeUnicode<'a>
type Item
#![allow(unused)] fn main() { type Item = char }
Тип элементов, по которым выполняется итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<char> }
Перемещает итератор и возвращает следующее значение.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
try_fold
#![allow(unused)] fn main() { fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where EscapeUnicode<'a>: Sized, Fold: FnMut(Acc, <EscapeUnicode<'a> as Iterator>::Item) -> R, R: Try<Output = Acc>, }
Метод итератора, который применяет функцию, пока она возвращает успех, производя единственное конечное значение.
fold
#![allow(unused)] fn main() { fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, <EscapeUnicode<'a> as Iterator>::Item) -> Acc, }
Складывает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_next_chunk #98326) Перемещает итератор и возвращает массив, содержащий следующие N значений.
count (с версии 1.0.0)
#![allow(unused)] fn main() { fn count(self) -> usize where Self: Sized, }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
last (с версии 1.0.0)
#![allow(unused)] fn main() { fn last(self) -> Option<Self::Item> where Self: Sized, }
Потребляет итератор, возвращая последний элемент.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_advance_by #77404) Перемещает итератор на n элементов.
nth (с версии 1.0.0)
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора.
step_by (с версии 1.28.0)
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом заданного размера на каждой итерации.
chain (с версии 1.0.0)
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip (с версии 1.0.0)
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
"Объединяет" два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map (с версии 1.0.0)
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Берет замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each (с версии 1.21.0)
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate (с версии 1.0.0)
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итераций, а также следующее значение.
peekable (с версии 1.0.0)
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления.
skip_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while (с версии 1.0.0)
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while (с версии 1.57.0)
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует их.
skip (с версии 1.0.0)
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take (с версии 1.0.0)
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов или меньше, если базовый итератор заканчивается раньше.
scan (с версии 1.0.0)
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map (с версии 1.0.0)
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но сглаживает вложенную структуру.
flatten (с версии 1.29.0)
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который сглаживает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого непрерывного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются.
fuse (с версии 1.0.0)
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который завершается после первого None.
inspect (с версии 1.0.0)
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Выполняет действие с каждым элементом итератора, передавая значение дальше.
by_ref (с версии 1.0.0)
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для данного экземпляра Iterator.
collect (с версии 1.0.0)
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_collect #94047) Преобразует итератор в коллекцию с обработкой ошибок, прерываясь при первой неудаче.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_collect_into #94780) Собирает все элементы из итератора в коллекцию.
partition (с версии 1.0.0)
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте в соответствии с заданным предикатом так, чтобы все элементы, возвращающие true, предшествовали всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_for_each (с версии 1.27.0)
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу итератора, останавливаясь при первой ошибке и возвращая эту ошибку.
reduce (с версии 1.51.0)
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному путем многократного применения операции сокращения.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iterator_try_reduce #87053) Сводит элементы к одному путем многократного применения операции сокращения. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
all (с версии 1.0.0)
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any (с версии 1.0.0)
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли хотя бы один элемент итератора предикату.
find (с версии 1.0.0)
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
find_map (с версии 1.30.0)
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (try_find #63178) Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
position (с версии 1.0.0)
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition (с версии 1.0.0)
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator, }
Ищет элемент в итераторе справа, возвращая его индекс.
max (с версии 1.0.0)
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min (с версии 1.0.0)
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение относительно указанной функции сравнения.
min_by_key (с версии 1.6.0)
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by (с версии 1.15.0)
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение относительно указанной функции сравнения.
rev (с версии 1.0.0)
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Изменяет направление итератора на противоположное.
unzip (с версии 1.0.0)
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied (с версии 1.36.0)
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned (с версии 1.0.0)
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle (с версии 1.0.0)
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_array_chunks #100450) Возвращает итератор по N элементов итератора за раз.
sum (с версии 1.11.0)
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product (с версии 1.11.0)
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
Итерируется по всему итератору, перемножая все элементы.
cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp (с версии 1.5.0)
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, оценка останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq (с версии 1.5.0)
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Это экспериментальное API, доступное только в ночных сборках. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne (с версии 1.5.0)
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt (с версии 1.5.0)
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше элементы этого Iterator, чем элементы другого.
le (с версии 1.5.0)
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли меньше или равны элементы этого Iterator элементам другого.
gt (с версии 1.5.0)
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше элементы этого Iterator, чем элементы другого.
ge (с версии 1.5.0)
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, лексикографически ли больше или равны элементы этого Iterator элементам другого.
is_sorted (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции сравнения.
is_sorted_by_key (с версии 1.82.0)
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl<'a> FusedIterator for EscapeUnicode<'a> (с версии 1.34.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for EscapeUnicode<'a> impl<'a> RefUnwindSafe for EscapeUnicode<'a> impl<'a> Send for EscapeUnicode<'a> impl<'a> Sync for EscapeUnicode<'a> impl<'a> Unpin for EscapeUnicode<'a> impl<'a> UnwindSafe for EscapeUnicode<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> ToString for T where T: Display + ?Sized, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Структура Lines
#![allow(unused)] fn main() { pub struct Lines<'a>(/* приватные поля */); }
Итератор по строкам текста (линиям) в виде срезов строк.
Эта структура создается методом lines для типа str. Подробнее см. в его документации.
Методы
impl<'a> Lines<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remaining = lines.remainder(); | 🔬 Экспериментальное API Возвращает оставшиеся строки разделенного текста |
Примеры
#![allow(unused)] #![feature(str_lines_remainder)] fn main() { let mut lines = "a\nb\nc\nd".lines(); assert_eq!(lines.remainder(), Some("a\nb\nc\nd")); lines.next(); assert_eq!(lines.remainder(), Some("b\nc\nd")); lines.by_ref().for_each(drop); assert_eq!(lines.remainder(), None); }
Реализации трейтов
impl<'a> Clone for Lines<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Lines<'a> ⓘ | let cloned = lines.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | lines.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a> Debug for Lines<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", lines); | Форматирует значение с помощью заданного форматтера |
impl<'a> DoubleEndedIterator for Lines<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_line = lines.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | lines.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = lines.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let concat = lines.try_rfold(String::new(), | mut s, line |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let concat = lines.rfold(String::new(), | mut s, line |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_empty = lines.rfind( | line |
impl<'a> Iterator for Lines<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| type Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация (срез строки) |
| next | fn next(&mut self) -> Option<&'a str> | let first_line = lines.next(); | Перемещает итератор и возвращает следующее значение |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let hint = lines.size_hint(); | Возвращает границы оставшейся длины итератора |
| last | fn last(self) -> Option<&'a str> | let last_line = lines.last(); | Возвращает последний элемент итератора |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = lines.next_chunk::<3>()?; | 🔬 Возвращает массив, содержащий следующие N значений |
| count | fn count(self) -> usize | let total_lines = lines.count(); | Подсчитывает количество итераций и возвращает его |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | lines.advance_by(2)?; | 🔬 Перемещает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third_line = lines.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let every_second = lines.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let combined = lines.chain(more_lines); | Объединяет два итератора в последовательный |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let paired = lines.zip(other_lines); | "Объединяет" два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_newline = lines.intersperse("\n"); | 🔬 Помещает копию separator между элементами |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = lines.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let uppercased = lines.map( | line |
| for_each | fn for_each<F>(self, f: F) | `lines.for_each( | line |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let non_empty = lines.filter( | line |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let lengths = lines.filter_map( | line |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, line) in lines.enumerate() { ... } | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = lines.peekable(); | Создает итератор с возможностью просмотра следующего элемента |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = lines.skip_while( | line |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = lines.take_while( | line |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = lines.map_while( | line |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = lines.skip(3); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = lines.take(5); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = lines.scan(0, | state, line |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let words = lines.flat_map( | line |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = lines.flatten(); | Сглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = lines.map_windows::<_, _, 2>( | arr |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = lines.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = lines.inspect( | line |
| by_ref | fn by_ref(&mut self) -> &mut Self | let part = lines.by_ref().take(5).collect::<Vec<_>>(); | Создает адаптер "по ссылке" для итератора |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = lines.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<Vec<&str>, _> = lines.try_collect(); | 🔬 Преобразует итератор в коллекцию с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | let mut vec = Vec::new(); lines.collect_into(&mut vec); | 🔬 Собирает все элементы в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (short, long): (Vec<&str>, Vec<&str>) = lines.partition( | line |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let count = lines.partition_in_place( | line |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = lines.is_partitioned( | line |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let total_len = lines.try_fold(0, | acc, line |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `let result: Result<(), _> = lines.try_for_each( | line |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = lines.fold(0, | acc, line |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = lines.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let result: Result<Option<&str>, _> = lines.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_non_empty = lines.all( | line |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_empty = lines.any( | line |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_long = lines.find( | line |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let first_num = lines.find_map( | line |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result: Result<Option<&str>, _> = lines.try_find( | line |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = lines.position( | line |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let pos = lines.rposition( | line |
| max | fn max(self) -> Option<Self::Item> | let longest = lines.max(); | Возвращает максимальный элемент (лексикографически) |
| min | fn min(self) -> Option<Self::Item> | let shortest = lines.min(); | Возвращает минимальный элемент (лексикографически) |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = lines.max_by_key( | line |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = lines.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = lines.min_by_key( | line |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = lines.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = lines.rev(); | Изменяет направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (lines, lengths): (Vec<&str>, Vec | line |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied_lines = lines.copied(); | Создает итератор, который копирует все элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned_lines = lines.cloned(); | Создает итератор, который клонирует все элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = lines.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | for chunk in lines.array_chunks::<3>() { ... } | 🔬 Возвращает итератор по N элементов за раз |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = lines.map( | line |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: usize = lines.map( | line |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = lines.cmp(other_lines); | Лексикографически сравнивает элементы с другими |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = lines.cmp_by(other_lines, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = lines.partial_cmp(other_lines); | Частично сравнивает элементы с другими |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = lines.partial_cmp_by(other_lines, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = lines.eq(other_lines); | Проверяет равенство элементов с другими |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = lines.eq_by(other_lines, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = lines.ne(other_lines); | Проверяет неравенство элементов с другими |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = lines.lt(other_lines); | Проверяет, меньше ли элементы, чем другие |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_or_equal = lines.le(other_lines); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = lines.gt(other_lines); | Проверяет, больше ли элементы, чем другие |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_or_equal = lines.ge(other_lines); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = lines.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = lines.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = lines.is_sorted_by_key( | line |
impl FusedIterator for Lines<'_> (с версии 1.26.0)
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a> Freeze for Lines<'a> impl<'a> RefUnwindSafe for Lines<'a> impl<'a> Send for Lines<'a> impl<'a> Sync for Lines<'a> impl<'a> Unpin for Lines<'a> impl<'a> UnwindSafe for Lines<'a> }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Обозначения:
- 🔬 - экспериментальное API, доступное только в ночных сборках
ⓘ- обозначение, что функция возвращает итератор
Структура MatchIndices
#![allow(unused)] fn main() { pub struct MatchIndices<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом match_indices.
Реализации трейтов
impl<'a, P> Clone for MatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> MatchIndices<'a, P> ⓘ | let cloned = match_indices.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | match_indices.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for MatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", match_indices); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for MatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<(usize, &'a str)> | let last_match = match_indices.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | match_indices.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = match_indices.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = match_indices.try_rfold(vec![], | mut v, (i, s) |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = match_indices.rfold(0, | acc, (_, s) |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = match_indices.rfind( | (_, s) |
impl<'a, P> Iterator for MatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| type Item | type Item = (usize, &'a str) | - | Тип элементов, по которым выполняется итерация (пара: индекс и срез строки) |
| next | fn next(&mut self) -> Option<(usize, &'a str)> | let first_match = match_indices.next(); | Перемещает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = match_indices.next_chunk::<3>()?; | 🔬 Возвращает массив, содержащий следующие N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let hint = match_indices.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total_matches = match_indices.count(); | Подсчитывает количество итераций и возвращает его |
| last | fn last(self) -> Option<Self::Item> | let last_match = match_indices.last(); | Возвращает последний элемент итератора |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | match_indices.advance_by(2)?; | 🔬 Перемещает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third_match = match_indices.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let every_second = match_indices.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let combined = match_indices.chain(other_matches); | Объединяет два итератора в последовательный |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let paired = match_indices.zip(other_data); | "Объединяет" два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = match_indices.intersperse((0, "")); | 🔬 Помещает копию separator между элементами |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = match_indices.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let indices = match_indices.map( | (i, _) |
| for_each | fn for_each<F>(self, f: F) | `match_indices.for_each( | (i, s) |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long_matches = match_indices.filter( | (_, s) |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let lengths = match_indices.filter_map( | (i, s) |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (j, (i, s)) in match_indices.enumerate() { ... } | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = match_indices.peekable(); | Создает итератор с возможностью просмотра следующего элемента |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = match_indices.skip_while( | (i, _) |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = match_indices.take_while( | (i, _) |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = match_indices.map_while( | (i, s) |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = match_indices.skip(3); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = match_indices.take(5); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = match_indices.scan(vec![], | state, (i, s) |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = match_indices.flat_map( | (_, s) |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = match_indices.flatten(); | Сглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = match_indices.map_windows::<_, _, 2>( | arr |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = match_indices.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = match_indices.inspect( | (i, s) |
| by_ref | fn by_ref(&mut self) -> &mut Self | let part = match_indices.by_ref().take(5).collect::<Vec<_>>(); | Создает адаптер "по ссылке" для итератора |
| collect | fn collect<B>(self) -> B | let vec: Vec<(usize, &str)> = match_indices.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<Vec<(usize, &str)>, _> = match_indices.try_collect(); | 🔬 Преобразует итератор в коллекцию с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | let mut vec = Vec::new(); match_indices.collect_into(&mut vec); | 🔬 Собирает все элементы в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (early, late): (Vec<>, Vec<>) = match_indices.partition( | (i, _) |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let count = match_indices.partition_in_place( | (i, _) |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = match_indices.is_partitioned( | (i, _) |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let total_len = match_indices.try_fold(0, | acc, (_, s) |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `let result: Result<(), _> = match_indices.try_for_each( | (i, s) |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = match_indices.fold(0, | acc, (_, s) |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = match_indices.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let result: Result<Option<(usize, &str)>, _> = match_indices.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = match_indices.all( | (_, s) |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_empty = match_indices.any( | (_, s) |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_long = match_indices.find( | (_, s) |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let first_num = match_indices.find_map( | (i, s) |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result: Result<Option<(usize, &str)>, _> = match_indices.try_find( | (_, s) |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = match_indices.position( | (_, s) |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let pos = match_indices.rposition( | (_, s) |
| max | fn max(self) -> Option<Self::Item> | let longest = match_indices.max(); | Возвращает максимальный элемент (лексикографически) |
| min | fn min(self) -> Option<Self::Item> | let shortest = match_indices.min(); | Возвращает минимальный элемент (лексикографически) |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let latest = match_indices.max_by_key( | (i, _) |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = match_indices.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let earliest = match_indices.min_by_key( | (i, _) |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = match_indices.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = match_indices.rev(); | Изменяет направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (indices, matches): (Vec<usize>, Vec<&str>) = match_indices.unzip(); | Преобразует итератор пар в пару контейнеров |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied = match_indices.copied(); | Создает итератор, который копирует все элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned = match_indices.cloned(); | Создает итератор, который клонирует все элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = match_indices.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | for chunk in match_indices.array_chunks::<3>() { ... } | 🔬 Возвращает итератор по N элементов за раз |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = match_indices.map( | (_, s) |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: usize = match_indices.map( | (_, s) |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = match_indices.cmp(other_matches); | Лексикографически сравнивает элементы с другими |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = match_indices.cmp_by(other_matches, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = match_indices.partial_cmp(other_matches); | Частично сравнивает элементы с другими |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = match_indices.partial_cmp_by(other_matches, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = match_indices.eq(other_matches); | Проверяет равенство элементов с другими |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = match_indices.eq_by(other_matches, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = match_indices.ne(other_matches); | Проверяет неравенство элементов с другими |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = match_indices.lt(other_matches); | Проверяет, меньше ли элементы, чем другие |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_or_equal = match_indices.le(other_matches); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = match_indices.gt(other_matches); | Проверяет, больше ли элементы, чем другие |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_or_equal = match_indices.ge(other_matches); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = match_indices.is_sorted(); | Проверяет, отсортированы ли элементы (по индексу) |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = match_indices.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = match_indices.is_sorted_by_key( | (i, _) |
impl<'a, P> FusedIterator for MatchIndices<'a, P> (с версии 1.26.0)
#![allow(unused)] fn main() { where P: Pattern, }
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl<'a, P> Freeze for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: Freeze, }
#![allow(unused)] fn main() { impl<'a, P> RefUnwindSafe for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: RefUnwindSafe, }
#![allow(unused)] fn main() { impl<'a, P> Send for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: Send, }
#![allow(unused)] fn main() { impl<'a, P> Sync for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: Sync, }
#![allow(unused)] fn main() { impl<'a, P> Unpin for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: Unpin, }
#![allow(unused)] fn main() { impl<'a, P> UnwindSafe for MatchIndices<'a, P> where <P as Pattern>::Searcher<'a>: UnwindSafe, }
Общие реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Обозначения:
- 🔬 - экспериментальное API, доступное только в ночных сборках
ⓘ- обозначение, что функция возвращает итераторP: Pattern- шаблон для поиска<P as Pattern>::Searcher<'a>- тип искателя для шаблона
Структура Matches
#![allow(unused)] fn main() { pub struct Matches<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом matches.
Реализации трейтов
impl<'a, P> Clone for Matches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Matches<'a, P> ⓘ | let cloned = matches.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | matches.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for Matches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", matches); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for Matches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_match = matches.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | matches.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = matches.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = matches.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = matches.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = matches.rfind( | s |
impl<'a, P> Iterator for Matches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_match = matches.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = matches.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = matches.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = matches.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_match = matches.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | matches.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = matches.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = matches.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = matches.chain(other_matches); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = matches.zip(other_matches); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = matches.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = matches.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = matches.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `matches.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = matches.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = matches.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in matches.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = matches.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = matches.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = matches.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = matches.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = matches.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = matches.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = matches.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = matches.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = matches.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = matches.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = matches.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = matches.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in matches.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = matches.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = matches.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | matches.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = matches.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = matches.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = matches.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = matches.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `matches.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = matches.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = matches.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = matches.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = matches.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = matches.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = matches.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = matches.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = matches.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = matches.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = matches.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = matches.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = matches.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = matches.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = matches.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = matches.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = matches.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = matches.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = matches.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = matches.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = matches.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = matches.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = matches.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = matches.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = matches.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = matches.cmp(other_matches); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = matches.cmp_by(other_matches, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = matches.partial_cmp(other_matches); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = matches.partial_cmp_by(other_matches, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = matches.eq(other_matches); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = matches.eq_by(other_matches, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = matches.ne(other_matches); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = matches.lt(other_matches); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = matches.le(other_matches); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = matches.gt(other_matches); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = matches.ge(other_matches); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = matches.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = matches.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = matches.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for Matches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура ParseBoolError
#![allow(unused)] fn main() { #[non_exhaustive] pub struct ParseBoolError; }
Ошибка, возвращаемая при неудачном парсинге bool с помощью from_str.
Реализации трейтов
impl Clone for ParseBoolError
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> ParseBoolError | let cloned = parse_bool_error.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | parse_bool_error.clone_from(&other); | Выполняет копирующее присваивание из source |
impl Debug for ParseBoolError
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", parse_bool_error); | Форматирует значение с помощью заданного форматтера для отладки |
impl Display for ParseBoolError
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("Ошибка: {}", parse_bool_error); | Форматирует значение для пользовательского отображения |
impl Error for ParseBoolError
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| source (с версии 1.30.0) | fn source(&self) -> Option<&(dyn Error + 'static)> | if let Some(source) = parse_bool_error.source() | Возвращает нижележащую причину ошибки, если она есть |
| description (устарело с версии 1.42.0) | fn description(&self) -> &str | let desc = parse_bool_error.description(); | 👎 Возвращает строковое описание ошибки (устарело) |
| cause (устарело с версии 1.33.0) | fn cause(&self) -> Option<&dyn Error> | if let Some(cause) = parse_bool_error.cause() | 👎 Возвращает причину ошибки (устарело, заменено на source) |
| provide | fn provide<'a>(&'a self, request: &mut Request<'a>) | parse_bool_error.provide(&mut request); | 🔬 Предоставляет контекстную информацию для отчетов об ошибках |
impl PartialEq for ParseBoolError
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| eq | fn eq(&self, other: &ParseBoolError) -> bool | if error1 == error2 | Проверяет равенство значений |
| ne | fn ne(&self, other: &Rhs) -> bool | if error1 != error2 | Проверяет неравенство значений |
impl Eq for ParseBoolError
(Этот трейт не добавляет новых методов, а только указывает, что отношение равенства является эквивалентностью.)
impl StructuralPartialEq for ParseBoolError
(Маркерный трейт, указывающий, что структура может участвовать в структурном сравнении равенства.)
Автоматические реализации трейтов
| Трейт | Назначение |
|---|---|
Freeze | Позволяет использовать тип в неизменяемых контекстах |
RefUnwindSafe | Безопасность при разматывании стека через ссылки |
Send | Может безопасно передаваться между потоками |
Sync | Может безопасно использоваться из нескольких потоков одновременно |
Unpin | Значение можно безопасно перемещать в памяти |
UnwindSafe | Безопасность при разматывании стека |
Структура RMatchIndices
#![allow(unused)] fn main() { pub struct RMatchIndices<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом rmatch_indices.
Реализации трейтов
impl<'a, P> Clone for RMatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> RMatchIndices<'a, P> ⓘ | let cloned = rmatch_indices.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | rmatch_indices.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for RMatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", rmatch_indices); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for RMatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<(usize, &'a str)> | let last_match = rmatch_indices.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rmatch_indices.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = rmatch_indices.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = rmatch_indices.try_rfold(vec![], | mut v, (i, s) |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = rmatch_indices.rfold(0, | acc, (_, s) |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = rmatch_indices.rfind( | (_, s) |
impl<'a, P> Iterator for RMatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = (usize, &'a str) | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<(usize, &'a str)> | let next_match = rmatch_indices.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [(usize, &str); 3] = rmatch_indices.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = rmatch_indices.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = rmatch_indices.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_match = rmatch_indices.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rmatch_indices.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = rmatch_indices.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = rmatch_indices.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = rmatch_indices.chain(other_indices); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = rmatch_indices.zip(other_indices); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = rmatch_indices.intersperse((0, "")); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = rmatch_indices.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let indices_only = rmatch_indices.map( | (i, _) |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `rmatch_indices.for_each( | (i, s) |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = rmatch_indices.filter( | (_, s) |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let lengths = rmatch_indices.filter_map( | (i, s) |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (iter_idx, (pos, s)) in rmatch_indices.enumerate() | Добавляет индекс итерации к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = rmatch_indices.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = rmatch_indices.skip_while( | (_, s) |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = rmatch_indices.take_while( | (_, s) |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let indices = rmatch_indices.map_while( | (i, s) |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = rmatch_indices.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = rmatch_indices.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let positions = rmatch_indices.scan(vec![], | v, (i, _) |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = rmatch_indices.flat_map( | (_, s) |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = rmatch_indices.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = rmatch_indices.map_windows( | arr: &[(usize, &str); 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = rmatch_indices.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = rmatch_indices.inspect( | (i, s) |
| by_ref | fn by_ref(&mut self) -> &mut Self | for (i, s) in rmatch_indices.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<(usize, &str)> = rmatch_indices.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<(usize, &str), _>> = rmatch_indices.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | rmatch_indices.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = rmatch_indices.partition( | (_, s) |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = rmatch_indices.partition_in_place( | (_, s) |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = rmatch_indices.is_partitioned( | (_, s) |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = rmatch_indices.try_fold(0, | acc, (_, s) |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `rmatch_indices.try_for_each( | (i, s) |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = rmatch_indices.fold(0, | acc, (_, s) |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = rmatch_indices.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = rmatch_indices.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = rmatch_indices.all( | (_, s) |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = rmatch_indices.any( | (_, s) |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = rmatch_indices.find( | (_, s) |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let pos = rmatch_indices.find_map( | (i, s) |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = rmatch_indices.try_find( | (_, s) |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = rmatch_indices.position( | (_, s) |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = rmatch_indices.rposition( | (_, s) |
| max | fn max(self) -> Option<Self::Item> | let longest = rmatch_indices.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = rmatch_indices.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = rmatch_indices.max_by_key( | (_, s) |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = rmatch_indices.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = rmatch_indices.min_by_key( | (_, s) |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = rmatch_indices.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = rmatch_indices.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (indices, strings): (Vec<usize>, Vec<&str>) = rmatch_indices.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = rmatch_indices.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = rmatch_indices.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = rmatch_indices.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = rmatch_indices.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = rmatch_indices.map( | (_, s) |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = rmatch_indices.map( | (_, s) |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = rmatch_indices.cmp(other_indices); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = rmatch_indices.cmp_by(other_indices, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = rmatch_indices.partial_cmp(other_indices); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = rmatch_indices.partial_cmp_by(other_indices, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = rmatch_indices.eq(other_indices); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = rmatch_indices.eq_by(other_indices, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = rmatch_indices.ne(other_indices); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = rmatch_indices.lt(other_indices); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = rmatch_indices.le(other_indices); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = rmatch_indices.gt(other_indices); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = rmatch_indices.ge(other_indices); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = rmatch_indices.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = rmatch_indices.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = rmatch_indices.is_sorted_by_key( | (_, s) |
impl<'a, P> FusedIterator for RMatchIndices<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура RMatches
#![allow(unused)] fn main() { pub struct RMatches<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом rmatches.
Реализации трейтов
impl<'a, P> Clone for RMatches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> RMatches<'a, P> ⓘ | let cloned = rmatches.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | rmatches.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for RMatches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", rmatches); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for RMatches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_match = rmatches.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rmatches.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = rmatches.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = rmatches.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = rmatches.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = rmatches.rfind( | s |
impl<'a, P> Iterator for RMatches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_match = rmatches.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = rmatches.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = rmatches.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = rmatches.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_match = rmatches.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rmatches.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = rmatches.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = rmatches.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = rmatches.chain(other_matches); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = rmatches.zip(other_matches); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = rmatches.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = rmatches.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = rmatches.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `rmatches.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = rmatches.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = rmatches.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in rmatches.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = rmatches.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = rmatches.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = rmatches.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = rmatches.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = rmatches.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = rmatches.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = rmatches.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = rmatches.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = rmatches.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = rmatches.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = rmatches.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = rmatches.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in rmatches.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = rmatches.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = rmatches.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | rmatches.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = rmatches.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = rmatches.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = rmatches.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = rmatches.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `rmatches.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = rmatches.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = rmatches.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = rmatches.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = rmatches.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = rmatches.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = rmatches.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = rmatches.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = rmatches.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = rmatches.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = rmatches.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = rmatches.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = rmatches.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = rmatches.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = rmatches.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = rmatches.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = rmatches.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = rmatches.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = rmatches.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = rmatches.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = rmatches.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = rmatches.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = rmatches.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = rmatches.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = rmatches.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = rmatches.cmp(other_matches); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = rmatches.cmp_by(other_matches, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = rmatches.partial_cmp(other_matches); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = rmatches.partial_cmp_by(other_matches, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = rmatches.eq(other_matches); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = rmatches.eq_by(other_matches, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = rmatches.ne(other_matches); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = rmatches.lt(other_matches); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = rmatches.le(other_matches); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = rmatches.gt(other_matches); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = rmatches.ge(other_matches); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = rmatches.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = rmatches.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = rmatches.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for RMatches<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура RSplit
#![allow(unused)] fn main() { pub struct RSplit<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом rsplit.
Методы
impl<'a, P> RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = rsplit.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> RSplit<'a, P> ⓘ | let cloned = rsplit.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | rsplit.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", rsplit); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_part = rsplit.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rsplit.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = rsplit.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = rsplit.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = rsplit.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = rsplit.rfind( | s |
impl<'a, P> Iterator for RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = rsplit.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = rsplit.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = rsplit.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = rsplit.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = rsplit.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rsplit.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = rsplit.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = rsplit.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = rsplit.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = rsplit.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = rsplit.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = rsplit.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = rsplit.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `rsplit.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = rsplit.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = rsplit.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in rsplit.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = rsplit.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = rsplit.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = rsplit.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = rsplit.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = rsplit.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = rsplit.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = rsplit.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = rsplit.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = rsplit.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = rsplit.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = rsplit.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = rsplit.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in rsplit.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = rsplit.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = rsplit.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | rsplit.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = rsplit.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = rsplit.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = rsplit.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = rsplit.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `rsplit.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = rsplit.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = rsplit.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = rsplit.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = rsplit.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = rsplit.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = rsplit.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = rsplit.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = rsplit.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = rsplit.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = rsplit.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = rsplit.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = rsplit.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = rsplit.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = rsplit.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = rsplit.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = rsplit.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = rsplit.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = rsplit.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = rsplit.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = rsplit.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = rsplit.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = rsplit.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = rsplit.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = rsplit.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = rsplit.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = rsplit.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = rsplit.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = rsplit.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = rsplit.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = rsplit.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = rsplit.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = rsplit.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = rsplit.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = rsplit.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = rsplit.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = rsplit.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = rsplit.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = rsplit.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for RSplit<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура RSplitN
#![allow(unused)] fn main() { pub struct RSplitN<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом rsplitn.
Методы
impl<'a, P> RSplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = rsplitn.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for RSplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> RSplitN<'a, P> ⓘ | let cloned = rsplitn.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | rsplitn.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for RSplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", rsplitn); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> Iterator for RSplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = rsplitn.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = rsplitn.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = rsplitn.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = rsplitn.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = rsplitn.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rsplitn.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = rsplitn.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = rsplitn.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = rsplitn.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = rsplitn.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = rsplitn.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = rsplitn.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = rsplitn.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `rsplitn.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = rsplitn.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = rsplitn.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in rsplitn.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = rsplitn.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = rsplitn.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = rsplitn.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = rsplitn.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = rsplitn.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = rsplitn.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = rsplitn.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = rsplitn.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = rsplitn.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = rsplitn.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = rsplitn.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = rsplitn.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in rsplitn.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = rsplitn.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = rsplitn.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | rsplitn.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = rsplitn.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = rsplitn.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = rsplitn.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = rsplitn.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `rsplitn.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = rsplitn.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = rsplitn.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = rsplitn.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = rsplitn.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = rsplitn.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = rsplitn.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = rsplitn.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = rsplitn.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = rsplitn.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = rsplitn.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = rsplitn.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = rsplitn.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = rsplitn.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = rsplitn.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = rsplitn.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = rsplitn.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = rsplitn.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = rsplitn.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = rsplitn.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = rsplitn.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = rsplitn.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = rsplitn.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = rsplitn.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = rsplitn.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = rsplitn.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = rsplitn.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = rsplitn.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = rsplitn.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = rsplitn.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = rsplitn.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = rsplitn.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = rsplitn.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = rsplitn.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = rsplitn.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = rsplitn.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = rsplitn.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = rsplitn.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = rsplitn.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for RSplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура RSplitTerminator
#![allow(unused)] fn main() { pub struct RSplitTerminator<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом rsplit_terminator.
Методы
impl<'a, P> RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = rsplit_terminator.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> RSplitTerminator<'a, P> ⓘ | let cloned = rsplit_terminator.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | rsplit_terminator.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", rsplit_terminator); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_part = rsplit_terminator.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rsplit_terminator.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = rsplit_terminator.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = rsplit_terminator.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = rsplit_terminator.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = rsplit_terminator.rfind( | s |
impl<'a, P> Iterator for RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = rsplit_terminator.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = rsplit_terminator.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = rsplit_terminator.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = rsplit_terminator.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = rsplit_terminator.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | rsplit_terminator.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = rsplit_terminator.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = rsplit_terminator.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = rsplit_terminator.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = rsplit_terminator.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = rsplit_terminator.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = rsplit_terminator.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = rsplit_terminator.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `rsplit_terminator.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = rsplit_terminator.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = rsplit_terminator.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in rsplit_terminator.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = rsplit_terminator.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = rsplit_terminator.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = rsplit_terminator.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = rsplit_terminator.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = rsplit_terminator.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = rsplit_terminator.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = rsplit_terminator.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = rsplit_terminator.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = rsplit_terminator.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = rsplit_terminator.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = rsplit_terminator.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = rsplit_terminator.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in rsplit_terminator.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = rsplit_terminator.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = rsplit_terminator.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | rsplit_terminator.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = rsplit_terminator.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = rsplit_terminator.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = rsplit_terminator.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = rsplit_terminator.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `rsplit_terminator.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = rsplit_terminator.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = rsplit_terminator.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = rsplit_terminator.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = rsplit_terminator.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = rsplit_terminator.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = rsplit_terminator.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = rsplit_terminator.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = rsplit_terminator.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = rsplit_terminator.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = rsplit_terminator.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = rsplit_terminator.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = rsplit_terminator.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = rsplit_terminator.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = rsplit_terminator.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = rsplit_terminator.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = rsplit_terminator.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = rsplit_terminator.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = rsplit_terminator.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = rsplit_terminator.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = rsplit_terminator.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = rsplit_terminator.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = rsplit_terminator.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = rsplit_terminator.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = rsplit_terminator.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = rsplit_terminator.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = rsplit_terminator.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = rsplit_terminator.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = rsplit_terminator.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = rsplit_terminator.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = rsplit_terminator.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = rsplit_terminator.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = rsplit_terminator.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = rsplit_terminator.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = rsplit_terminator.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = rsplit_terminator.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = rsplit_terminator.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = rsplit_terminator.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = rsplit_terminator.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for RSplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: ReverseSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура Split
#![allow(unused)] fn main() { pub struct Split<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом split.
Методы
impl<'a, P> Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = split.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Split<'a, P> ⓘ | let cloned = split.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | split.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", split); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_part = split.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = split.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = split.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = split.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = split.rfind( | s |
impl<'a, P> Iterator for Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = split.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = split.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = split.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = split.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = split.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = split.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = split.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = split.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = split.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = split.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = split.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = split.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `split.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = split.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = split.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in split.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = split.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = split.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = split.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = split.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = split.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = split.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = split.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = split.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = split.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = split.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = split.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = split.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in split.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = split.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = split.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | split.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = split.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = split.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = split.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = split.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `split.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = split.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = split.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = split.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = split.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = split.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = split.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = split.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = split.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = split.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = split.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = split.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = split.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = split.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = split.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = split.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = split.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = split.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = split.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = split.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = split.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = split.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = split.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = split.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = split.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = split.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = split.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = split.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = split.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = split.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = split.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = split.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = split.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = split.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = split.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = split.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = split.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = split.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = split.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for Split<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура SplitAsciiWhitespace
#![allow(unused)] fn main() { pub struct SplitAsciiWhitespace<'a> { /* приватные поля */ } }
Итератор по подстрокам, не являющимся ASCII-пробельными символами, разделенными любым количеством ASCII-пробельных символов.
Эта структура создается методом split_ascii_whitespace для str. Смотрите его документацию для получения дополнительной информации.
Методы
impl<'a> SplitAsciiWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = split_ascii_whitespace.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a> Clone for SplitAsciiWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> SplitAsciiWhitespace<'a> ⓘ | let cloned = split_ascii_whitespace.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | split_ascii_whitespace.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a> Debug for SplitAsciiWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", split_ascii_whitespace); | Форматирует значение с помощью заданного форматтера |
impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_word = split_ascii_whitespace.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split_ascii_whitespace.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = split_ascii_whitespace.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = split_ascii_whitespace.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = split_ascii_whitespace.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = split_ascii_whitespace.rfind( | s |
impl<'a> Iterator for SplitAsciiWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_word = split_ascii_whitespace.next(); | Продвигает итератор и возвращает следующее значение |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = split_ascii_whitespace.size_hint(); | Возвращает границы оставшейся длины итератора |
| last | fn last(self) -> Option<&'a str> | let final_word = split_ascii_whitespace.last(); | Потребляет итератор, возвращая последний элемент |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = split_ascii_whitespace.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| count | fn count(self) -> usize | let total = split_ascii_whitespace.count(); | Потребляет итератор, подсчитывая количество итераций |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split_ascii_whitespace.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = split_ascii_whitespace.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = split_ascii_whitespace.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = split_ascii_whitespace.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = split_ascii_whitespace.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = split_ascii_whitespace.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = split_ascii_whitespace.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = split_ascii_whitespace.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `split_ascii_whitespace.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = split_ascii_whitespace.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = split_ascii_whitespace.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in split_ascii_whitespace.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = split_ascii_whitespace.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = split_ascii_whitespace.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = split_ascii_whitespace.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = split_ascii_whitespace.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = split_ascii_whitespace.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = split_ascii_whitespace.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = split_ascii_whitespace.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = split_ascii_whitespace.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = split_ascii_whitespace.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = split_ascii_whitespace.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = split_ascii_whitespace.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = split_ascii_whitespace.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in split_ascii_whitespace.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = split_ascii_whitespace.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = split_ascii_whitespace.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | split_ascii_whitespace.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = split_ascii_whitespace.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = split_ascii_whitespace.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = split_ascii_whitespace.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = split_ascii_whitespace.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `split_ascii_whitespace.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = split_ascii_whitespace.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = split_ascii_whitespace.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = split_ascii_whitespace.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = split_ascii_whitespace.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = split_ascii_whitespace.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = split_ascii_whitespace.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = split_ascii_whitespace.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = split_ascii_whitespace.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = split_ascii_whitespace.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = split_ascii_whitespace.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = split_ascii_whitespace.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = split_ascii_whitespace.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = split_ascii_whitespace.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = split_ascii_whitespace.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = split_ascii_whitespace.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = split_ascii_whitespace.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = split_ascii_whitespace.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = split_ascii_whitespace.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = split_ascii_whitespace.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = split_ascii_whitespace.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = split_ascii_whitespace.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = split_ascii_whitespace.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = split_ascii_whitespace.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = split_ascii_whitespace.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = split_ascii_whitespace.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = split_ascii_whitespace.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = split_ascii_whitespace.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = split_ascii_whitespace.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = split_ascii_whitespace.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = split_ascii_whitespace.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = split_ascii_whitespace.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = split_ascii_whitespace.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = split_ascii_whitespace.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = split_ascii_whitespace.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = split_ascii_whitespace.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = split_ascii_whitespace.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = split_ascii_whitespace.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = split_ascii_whitespace.is_sorted_by_key( | s |
impl FusedIterator for SplitAsciiWhitespace<'_>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Назначение |
|---|---|
Freeze | Позволяет использовать тип в неизменяемых контекстах |
RefUnwindSafe | Безопасность при разматывании стека через ссылки |
Send | Может безопасно передаваться между потоками |
Sync | Может безопасно использоваться из нескольких потоков одновременно |
Unpin | Значение можно безопасно перемещать в памяти |
UnwindSafe | Безопасность при разматывании стека |
Структура SplitInclusive
#![allow(unused)] fn main() { pub struct SplitInclusive<'a, P>(/* приватные поля */) where P: Pattern; }
Итератор по подстрокам строки, завершающимся подстрокой, соответствующей предикату. В отличие от Split, он содержит совпадающую часть как терминатор подстроки.
Эта структура создается методом split_inclusive для str. Смотрите его документацию для получения дополнительной информации.
Методы
impl<'a, P> SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = split_inclusive.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> SplitInclusive<'a, P> ⓘ | let cloned = split_inclusive.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | split_inclusive.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", split_inclusive); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last_part = split_inclusive.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split_inclusive.advance_back_by(2)?; | 🔬 Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = split_inclusive.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = split_inclusive.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = split_inclusive.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = split_inclusive.rfind( | s |
impl<'a, P> Iterator for SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = split_inclusive.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = split_inclusive.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = split_inclusive.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = split_inclusive.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = split_inclusive.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split_inclusive.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = split_inclusive.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = split_inclusive.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = split_inclusive.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = split_inclusive.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = split_inclusive.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = split_inclusive.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = split_inclusive.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `split_inclusive.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = split_inclusive.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = split_inclusive.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in split_inclusive.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = split_inclusive.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = split_inclusive.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = split_inclusive.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = split_inclusive.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = split_inclusive.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = split_inclusive.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = split_inclusive.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = split_inclusive.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = split_inclusive.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = split_inclusive.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = split_inclusive.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = split_inclusive.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in split_inclusive.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = split_inclusive.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = split_inclusive.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | split_inclusive.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = split_inclusive.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = split_inclusive.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = split_inclusive.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = split_inclusive.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `split_inclusive.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = split_inclusive.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = split_inclusive.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = split_inclusive.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = split_inclusive.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = split_inclusive.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = split_inclusive.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = split_inclusive.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = split_inclusive.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = split_inclusive.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = split_inclusive.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = split_inclusive.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = split_inclusive.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = split_inclusive.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = split_inclusive.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = split_inclusive.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = split_inclusive.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = split_inclusive.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = split_inclusive.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = split_inclusive.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = split_inclusive.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = split_inclusive.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = split_inclusive.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = split_inclusive.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = split_inclusive.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = split_inclusive.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = split_inclusive.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = split_inclusive.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = split_inclusive.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = split_inclusive.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = split_inclusive.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = split_inclusive.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = split_inclusive.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = split_inclusive.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = split_inclusive.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = split_inclusive.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = split_inclusive.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = split_inclusive.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = split_inclusive.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for SplitInclusive<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура SplitN
#![allow(unused)] fn main() { pub struct SplitN<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом splitn.
Методы
impl<'a, P> SplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = splitn.remainder(); | 🔬 Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
Реализации трейтов
impl<'a, P> Clone for SplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> SplitN<'a, P> ⓘ | let cloned = splitn.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | splitn.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for SplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", splitn); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> Iterator for SplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item | type Item = &'a str | - | Тип элементов, по которым выполняется итерация |
| next | fn next(&mut self) -> Option<&'a str> | let next_part = splitn.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk: [&str; 3] = splitn.next_chunk()?; | 🔬 Возвращает массив следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = splitn.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = splitn.count(); | Потребляет итератор, подсчитывая количество итераций |
| last | fn last(self) -> Option<Self::Item> | let final_part = splitn.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | splitn.advance_by(2)?; | 🔬 Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = splitn.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = splitn.step_by(2); | Создает итератор с заданным шагом |
| chain | fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> ⓘ | let combined = splitn.chain(other_split); | Объединяет два итератора в последовательности |
| zip | fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> ⓘ | let zipped = splitn.zip(other_split); | Объединяет два итератора в итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let with_sep = splitn.intersperse(", "); | 🔬 Разделяет элементы разделителем |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = splitn.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = splitn.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `splitn.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let long = splitn.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = splitn.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in splitn.enumerate() | Добавляет индекс к каждому элементу |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = splitn.peekable(); | Создает итератор с возможностью заглядывания вперед |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = splitn.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = splitn.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let nums = splitn.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = splitn.skip(2); | Пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let first_3 = splitn.take(3); | Берет первые n элементов |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = splitn.scan(0, | sum, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let chars = splitn.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = splitn.flatten(); | Разворачивает вложенные структуры |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = splitn.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = splitn.fuse(); | Создает итератор, завершающийся после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = splitn.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | for s in splitn.by_ref().take(2) | Создает ссылку на итератор |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = splitn.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> ... | let vec: Vec<Result<&str, _>> = splitn.try_collect(); | 🔬 Преобразует итератор с обработкой ошибок |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | splitn.collect_into(&mut vec); | 🔬 Собирает элементы в существующую коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (long, short): (Vec<>, Vec<>) = splitn.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = splitn.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = splitn.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = splitn.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `splitn.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = splitn.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = splitn.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> ... | `let longest = splitn.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_long = splitn.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let any_long = splitn.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let long = splitn.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let num = splitn.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> ... | `let long = splitn.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = splitn.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = splitn.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let longest = splitn.max(); | Возвращает максимальный элемент |
| min | fn min(self) -> Option<Self::Item> | let shortest = splitn.min(); | Возвращает минимальный элемент |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = splitn.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = splitn.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = splitn.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = splitn.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = splitn.rev(); | Обращает направление итератора |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | let (first, second): (Vec<_>, Vec<_>) = splitn.unzip(); | Разделяет пары на две коллекции |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = splitn.copied(); | Создает итератор, копирующий элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = splitn.cloned(); | Создает итератор, клонирующий элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = splitn.cycle(); | Бесконечно повторяет итератор |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = splitn.array_chunks::<3>(); | 🔬 Возвращает элементы массивами по N штук |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = splitn.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: i32 = splitn.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | let ordering = splitn.cmp(other_split); | Лексикографически сравнивает с другим итератором |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `let ordering = splitn.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | let ordering = splitn.partial_cmp(other_split); | Частично сравнивает с другим итератором |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `let ordering = splitn.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | let equal = splitn.eq(other_split); | Проверяет равенство элементов |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `let equal = splitn.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | let not_equal = splitn.ne(other_split); | Проверяет неравенство элементов |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | let less = splitn.lt(other_split); | Проверяет, меньше ли элементы |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | let less_equal = splitn.le(other_split); | Проверяет, меньше или равны ли элементы |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | let greater = splitn.gt(other_split); | Проверяет, больше ли элементы |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | let greater_equal = splitn.ge(other_split); | Проверяет, больше или равны ли элементы |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = splitn.is_sorted(); | Проверяет, отсортированы ли элементы |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = splitn.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = splitn.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for SplitN<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
(Этот трейт не добавляет новых методов, а только гарантирует, что после первого None все последующие вызовы next() также будут возвращать None. Это свойство наследуется от итератора.) |
Автоматические реализации трейтов
| Трейт | Условия реализации |
|---|---|
Freeze | Если Pattern::Searcher<'a>: Freeze |
RefUnwindSafe | Если Pattern::Searcher<'a>: RefUnwindSafe |
Send | Если Pattern::Searcher<'a>: Send |
Sync | Если Pattern::Searcher<'a>: Sync |
Unpin | Если Pattern::Searcher<'a>: Unpin |
UnwindSafe | Если Pattern::Searcher<'a>: UnwindSafe |
Структура SplitTerminator
#![allow(unused)] fn main() { pub struct SplitTerminator<'a, P>(/* приватные поля */) where P: Pattern; }
Создается методом split_terminator.
Реализации трейтов
impl<'a, P> SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = split.remainder(); | 🔬 Ночная экспериментальная функция (str_split_remainder #77998). Возвращает оставшуюся часть разделяемой строки. Если итератор пуст, возвращает None |
impl<'a, P> Clone for SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Clone, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> SplitTerminator<'a, P> ⓘ | let cloned = split.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | split.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a, P> Debug for SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: Debug, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", split); | Форматирует значение с помощью заданного форматтера |
impl<'a, P> DoubleEndedIterator for SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, <P as Pattern>::Searcher<'a>: DoubleEndedSearcher<'a>, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last = split.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_back_by(2)?; | 🔬 Ночная экспериментальная функция (iter_advance_by #77404). Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = split.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = split.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = split.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = split.rfind( | s |
impl<'a, P> Iterator for SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item (тип) | type Item = &'a str | Тип элементов, по которым производится итерация | |
| next | fn next(&mut self) -> Option<&'a str> | let next_item = split.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = split.next_chunk::<3>()?; | 🔬 Ночная экспериментальная функция (iter_next_chunk #98326). Продвигает итератор и возвращает массив из следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = split.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = split.count(); | Потребляет итератор, подсчитывая количество итераций и возвращая его |
| last | fn last(self) -> Option<Self::Item> | let last = split.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_by(3)?; | 🔬 Ночная экспериментальная функция (iter_advance_by #77404). Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = split.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = split.step_by(2); | Создает итератор, начинающийся с той же точки, но пропускающий заданное количество элементов на каждой итерации |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let chained = split.chain(other_iter); | Берет два итератора и создает новый итератор, проходящий по обоим последовательно |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let zipped = split.zip(other_iter); | "Сшивает" два итератора в один итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let interspersed = split.intersperse(","); | 🔬 Ночная экспериментальная функция (iter_intersperse #79524). Создает новый итератор, который помещает копию разделителя между соседними элементами исходного итератора |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = split.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = split.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `split.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let filtered = split.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = split.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in split.enumerate() | Создает итератор, который дает текущий счетчик итераций, а также следующее значение |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = split.peekable(); | Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = split.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = split.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = split.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = split.skip(2); | Создает итератор, который пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = split.take(3); | Создает итератор, который выдает первые n элементов или меньше, если базовый итератор закончится раньше |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = split.scan(0, | acc, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let flat = split.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = split.flatten(); | Создает итератор, который разглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = split.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = split.fuse(); | Создает итератор, который завершается после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = split.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | split.by_ref().take(5).for_each(...); | Создает "по ссылке" адаптер для этого экземпляра Iterator |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = split.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<Vec<_>, _> = split.try_collect(); | 🔬 Ночная экспериментальная функция (iterator_try_collect #94047). Пытается преобразовать итератор в коллекцию, замыкаясь при первой ошибке |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | split.collect_into(&mut vec); | 🔬 Ночная экспериментальная функция (iter_collect_into #94780). Собирает все элементы из итератора в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (empty, non_empty) = split.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = split.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = split.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = split.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `split.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = split.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = split.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let longest = split.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_non_empty = split.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_empty = split.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_long = split.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let first_num = split.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result = split.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = split.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = split.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let max_str = split.max(); | Возвращает максимальный элемент итератора |
| min | fn min(self) -> Option<Self::Item> | let min_str = split.min(); | Возвращает минимальный элемент итератора |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = split.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = split.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = split.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = split.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = split.rev(); | Меняет направление итератора на противоположное |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (lengths, strings): (Vec | s |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = split.copied(); | Создает итератор, который копирует все свои элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = split.cloned(); | Создает итератор, который клонирует все свои элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = split.cycle(); | Повторяет итератор бесконечно |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = split.array_chunks::<3>(); | 🔬 Ночная экспериментальная функция (iter_array_chunks #100450). Возвращает итератор по N элементам итератора за раз |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = split.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: usize = split.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | split.cmp(other_split) | Лексикографически сравнивает элементы этого Iterator с элементами другого |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `split.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | split.partial_cmp(other_split) | Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `split.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | split.eq(other_split) | Определяет, равны ли элементы этого Iterator элементам другого |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `split.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | split.ne(other_split) | Определяет, не равны ли элементы этого Iterator элементам другого |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | split.lt(other_split) | Определяет, являются ли элементы этого Iterator лексикографически меньше элементов другого |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | split.le(other_split) | Определяет, являются ли элементы этого Iterator лексикографически меньше или равны элементам другого |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | split.gt(other_split) | Определяет, являются ли элементы этого Iterator лексикографически больше элементов другого |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | split.ge(other_split) | Определяет, являются ли элементы этого Iterator лексикографически больше или равны элементам другого |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = split.is_sorted(); | Проверяет, отсортированы ли элементы этого итератора |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = split.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = split.is_sorted_by_key( | s |
impl<'a, P> FusedIterator for SplitTerminator<'a, P>
#![allow(unused)] fn main() { where P: Pattern, }
Этот трейт не имеет методов, но гарантирует, что после исчерпания итератор всегда будет возвращать None
Структура SplitWhitespace
#![allow(unused)] fn main() { pub struct SplitWhitespace<'a> { /* приватные поля */ } }
Итератор по непробельным подстрокам строки, разделенным любым количеством пробелов.
Этот структ создается методом split_whitespace для str. См. его документацию для получения дополнительной информации.
Реализации трейтов
impl<'a> SplitWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| remainder | pub fn remainder(&self) -> Option<&'a str> | let remainder = split.remainder(); | 🔬 Ночная экспериментальная функция (str_split_whitespace_remainder #77998). Возвращает оставшуюся часть разделяемой строки |
impl<'a> Clone for SplitWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> SplitWhitespace<'a> ⓘ | let cloned = split.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | split.clone_from(&other); | Выполняет копирующее присваивание из source |
impl<'a> Debug for SplitWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", split); | Форматирует значение с помощью заданного форматтера |
impl<'a> DoubleEndedIterator for SplitWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| next_back | fn next_back(&mut self) -> Option<&'a str> | let last = split.next_back(); | Удаляет и возвращает элемент с конца итератора |
| advance_back_by | fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_back_by(2)?; | 🔬 Ночная экспериментальная функция (iter_advance_by #77404). Перемещает итератор с конца на n элементов |
| nth_back (с версии 1.37.0) | fn nth_back(&mut self, n: usize) -> Option<Self::Item> | let second_last = split.nth_back(1); | Возвращает n-й элемент с конца итератора |
| try_rfold (с версии 1.27.0) | fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R | `let result = split.try_rfold(vec![], | mut v, s |
| rfold (с версии 1.27.0) | fn rfold<B, F>(self, init: B, f: F) -> B | `let total_len = split.rfold(0, | acc, s |
| rfind (с версии 1.27.0) | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | `let last_long = split.rfind( | s |
impl<'a> Iterator for SplitWhitespace<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item (тип) | type Item = &'a str | Тип элементов, по которым производится итерация | |
| next | fn next(&mut self) -> Option<&'a str> | let next_item = split.next(); | Продвигает итератор и возвращает следующее значение |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = split.size_hint(); | Возвращает границы оставшейся длины итератора |
| last | fn last(self) -> Option<&'a str> | let last = split.last(); | Потребляет итератор, возвращая последний элемент |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> | let chunk = split.next_chunk::<3>()?; | 🔬 Ночная экспериментальная функция (iter_next_chunk #98326). Продвигает итератор и возвращает массив из следующих N значений |
| count | fn count(self) -> usize | let total = split.count(); | Потребляет итератор, подсчитывая количество итераций и возвращая его |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | split.advance_by(3)?; | 🔬 Ночная экспериментальная функция (iter_advance_by #77404). Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third = split.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = split.step_by(2); | Создает итератор, начинающийся с той же точки, но пропускающий заданное количество элементов на каждой итерации |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let chained = split.chain(other_iter); | Берет два итератора и создает новый итератор, проходящий по обоим последовательно |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let zipped = split.zip(other_iter); | "Сшивает" два итератора в один итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let interspersed = split.intersperse(","); | 🔬 Ночная экспериментальная функция (iter_intersperse #79524). Создает новый итератор, который помещает копию разделителя между соседними элементами исходного итератора |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = split.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let lengths = split.map( | s |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `split.for_each( | s |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let filtered = split.filter( | s |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let nums = split.filter_map( | s |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, s) in split.enumerate() | Создает итератор, который дает текущий счетчик итераций, а также следующее значение |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = split.peekable(); | Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let skipped = split.skip_while( | s |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let taken = split.take_while( | s |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let mapped = split.map_while( | s |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = split.skip(2); | Создает итератор, который пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = split.take(3); | Создает итератор, который выдает первые n элементов или меньше, если базовый итератор закончится раньше |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = split.scan(0, | acc, s |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let flat = split.flat_map( | s |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = split.flatten(); | Создает итератор, который разглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = split.map_windows( | arr: &[&str; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = split.fuse(); | Создает итератор, который завершается после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = split.inspect( | s |
| by_ref | fn by_ref(&mut self) -> &mut Self | split.by_ref().take(5).for_each(...); | Создает "по ссылке" адаптер для этого экземпляра Iterator |
| collect | fn collect<B>(self) -> B | let vec: Vec<&str> = split.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<Vec<_>, _> = split.try_collect(); | 🔬 Ночная экспериментальная функция (iterator_try_collect #94047). Пытается преобразовать итератор в коллекцию, замыкаясь при первой ошибке |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | split.collect_into(&mut vec); | 🔬 Ночная экспериментальная функция (iter_collect_into #94780). Собирает все элементы из итератора в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (empty, non_empty) = split.partition( | s |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = split.partition_in_place( | s |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = split.is_partitioned( | s |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let sum = split.try_fold(0, | acc, s |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `split.try_for_each( | s |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_len = split.fold(0, | acc, s |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let longest = split.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let longest = split.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_non_empty = split.all( | s |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_empty = split.any( | s |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_long = split.find( | s |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let first_num = split.find_map( | s |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result = split.try_find( | s |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = split.position( | s |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = split.rposition( | s |
| max | fn max(self) -> Option<Self::Item> | let max_str = split.max(); | Возвращает максимальный элемент итератора |
| min | fn min(self) -> Option<Self::Item> | let min_str = split.min(); | Возвращает минимальный элемент итератора |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest = split.max_by_key( | s |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = split.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest = split.min_by_key( | s |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = split.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = split.rev(); | Меняет направление итератора на противоположное |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (lengths, strings): (Vec | s |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = split.copied(); | Создает итератор, который копирует все свои элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = split.cloned(); | Создает итератор, который клонирует все свои элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = split.cycle(); | Повторяет итератор бесконечно |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = split.array_chunks::<3>(); | 🔬 Ночная экспериментальная функция (iter_array_chunks #100450). Возвращает итератор по N элементам итератора за раз |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = split.map( | s |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: usize = split.map( | s |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | split.cmp(other_split) | Лексикографически сравнивает элементы этого Iterator с элементами другого |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `split.cmp_by(other_split, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | split.partial_cmp(other_split) | Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `split.partial_cmp_by(other_split, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | split.eq(other_split) | Определяет, равны ли элементы этого Iterator элементам другого |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `split.eq_by(other_split, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | split.ne(other_split) | Определяет, не равны ли элементы этого Iterator элементам другого |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | split.lt(other_split) | Определяет, являются ли элементы этого Iterator лексикографически меньше элементов другого |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | split.le(other_split) | Определяет, являются ли элементы этого Iterator лексикографически меньше или равны элементам другого |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | split.gt(other_split) | Определяет, являются ли элементы этого Iterator лексикографически больше элементов другого |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | split.ge(other_split) | Определяет, являются ли элементы этого Iterator лексикографически больше или равны элементам другого |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = split.is_sorted(); | Проверяет, отсортированы ли элементы этого итератора |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = split.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = split.is_sorted_by_key( | s |
impl FusedIterator for SplitWhitespace<'_>
Этот трейт не имеет методов, но гарантирует, что после исчерпания итератор всегда будет возвращать None
Структура Utf8Chunk
#![allow(unused)] fn main() { pub struct Utf8Chunk<'a> { /* приватные поля */ } }
Элемент, возвращаемый итератором Utf8Chunks.
Utf8Chunk хранит последовательность байтов u8 до первого поврежденного символа при декодировании UTF-8 строки.
Примеры
#![allow(unused)] fn main() { // Неверная UTF-8 строка let bytes = b"foo\xF1\x80bar"; // Декодируем первый `Utf8Chunk` let chunk = bytes.utf8_chunks().next().unwrap(); // Первые три символа - валидные UTF-8 assert_eq!("foo", chunk.valid()); // Четвертый символ поврежден assert_eq!(b"\xF1\x80", chunk.invalid()); }
Реализации трейтов
impl<'a> Utf8Chunk<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| valid | pub fn valid(&self) -> &'a str | let valid_part = chunk.valid(); | Возвращает следующую валидную UTF-8 подстроку. Эта подстрока может быть пустой в начале строки или между поврежденными UTF-8 символами |
| invalid | pub fn invalid(&self) -> &'a [u8] ⓘ | let invalid_bytes = chunk.invalid(); | Возвращает невалидную последовательность, которая вызвала ошибку. Возвращаемый срез будет иметь максимальную длину 3 и начинается после подстроки, заданной valid. Декодирование продолжится после этой последовательности. Если пусто, это последний чанк в строке. Если не пусто, встретился неожиданный байт или неожиданно достигнут конец ввода. Потерянное декодирование заменит эту последовательность на U+FFFD REPLACEMENT CHARACTER |
impl<'a> Clone for Utf8Chunk<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Utf8Chunk<'a> | let cloned_chunk = chunk.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | chunk.clone_from(&other_chunk); | Выполняет копирующее присваивание из source |
impl<'a> Debug for Utf8Chunk<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", chunk); | Форматирует значение с помощью заданного форматтера |
impl<'a> PartialEq for Utf8Chunk<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| eq | fn eq(&self, other: &Utf8Chunk<'a>) -> bool | if chunk1 == chunk2 { ... } | Проверяет равенство значений self и other, используется оператором == |
| ne | fn ne(&self, other: &Rhs) -> bool | if chunk1 != chunk2 { ... } | Проверяет неравенство. Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины |
impl<'a> Eq for Utf8Chunk<'a>
Этот трейт не имеет методов, но указывает, что тип реализует отношение эквивалентности (рефлексивность, симметричность, транзитивность)
impl<'a> StructuralPartialEq for Utf8Chunk<'a>
Этот трейт не имеет методов и используется для указания структурного равенства в макросах
Структура Utf8Chunks
#![allow(unused)] fn main() { pub struct Utf8Chunks<'a> { /* приватные поля */ } }
Итератор для декодирования среза байтов, преимущественно в кодировке UTF-8, в срезы строк (&str) и срезы байтов (&[u8]).
Этот структ создается методом utf8_chunks для срезов байтов. Если вам нужна простая конвертация из срезов UTF-8 байтов в срезы строк, проще использовать from_utf8.
См. документацию типа Utf8Chunk для информации о элементах, возвращаемых этим итератором.
Примеры
Можно использовать для создания функциональности, аналогичной String::from_utf8_lossy, без выделения памяти в куче:
#![allow(unused)] fn main() { fn from_utf8_lossy<F>(input: &[u8], mut push: F) where F: FnMut(&str) { for chunk in input.utf8_chunks() { push(chunk.valid()); if !chunk.invalid().is_empty() { push("\u{FFFD}"); } } } }
Реализации трейтов
impl<'a> Clone for Utf8Chunks<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Utf8Chunks<'a> ⓘ | let cloned = utf8_chunks.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | utf8_chunks.clone_from(&other); | Выполняет копирующее присваивание из source |
impl Debug for Utf8Chunks<'_>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", utf8_chunks); | Форматирует значение с помощью заданного форматтера |
impl<'a> Iterator for Utf8Chunks<'a>
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| Item (тип) | type Item = Utf8Chunk<'a> | Тип элементов, по которым производится итерация | |
| next | fn next(&mut self) -> Option<Utf8Chunk<'a>> | let chunk = utf8_chunks.next(); | Продвигает итератор и возвращает следующее значение |
| next_chunk | fn next_chunk<const N: usize>(&mut self) -> Result<([Self::Item; N], IntoIter<Self::Item, N>)> | let chunks = utf8_chunks.next_chunk::<3>()?; | 🔬 Ночная экспериментальная функция (iter_next_chunk #98326). Продвигает итератор и возвращает массив из следующих N значений |
| size_hint | fn size_hint(&self) -> (usize, Option<usize>) | let (min, max) = utf8_chunks.size_hint(); | Возвращает границы оставшейся длины итератора |
| count | fn count(self) -> usize | let total = utf8_chunks.count(); | Потребляет итератор, подсчитывая количество итераций и возвращая его |
| last | fn last(self) -> Option<Self::Item> | let last_chunk = utf8_chunks.last(); | Потребляет итератор, возвращая последний элемент |
| advance_by | fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> | utf8_chunks.advance_by(3)?; | 🔬 Ночная экспериментальная функция (iter_advance_by #77404). Продвигает итератор на n элементов |
| nth | fn nth(&mut self, n: usize) -> Option<Self::Item> | let third_chunk = utf8_chunks.nth(2); | Возвращает n-й элемент итератора |
| step_by (с версии 1.28.0) | fn step_by(self, step: usize) -> StepBy<Self> ⓘ | let stepped = utf8_chunks.step_by(2); | Создает итератор, начинающийся с той же точки, но пропускающий заданное количество элементов на каждой итерации |
| chain | fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ | let chained = utf8_chunks.chain(other_iter); | Берет два итератора и создает новый итератор, проходящий по обоим последовательно |
| zip | fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ | let zipped = utf8_chunks.zip(other_iter); | "Сшивает" два итератора в один итератор пар |
| intersperse | fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ | let interspersed = utf8_chunks.intersperse(separator); | 🔬 Ночная экспериментальная функция (iter_intersperse #79524). Создает новый итератор, который помещает копию разделителя между соседними элементами исходного итератора |
| intersperse_with | fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ | `let with_sep = utf8_chunks.intersperse_with( | |
| map | fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ | `let valid_parts = utf8_chunks.map( | c |
| for_each (с версии 1.21.0) | fn for_each<F>(self, f: F) | `utf8_chunks.for_each( | chunk |
| filter | fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ | `let valid_chunks = utf8_chunks.filter( | c |
| filter_map | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ | `let valid_strings = utf8_chunks.filter_map( | c |
| enumerate | fn enumerate(self) -> Enumerate<Self> ⓘ | for (i, chunk) in utf8_chunks.enumerate() | Создает итератор, который дает текущий счетчик итераций, а также следующее значение |
| peekable | fn peekable(self) -> Peekable<Self> ⓘ | let peekable = utf8_chunks.peekable(); | Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления |
| skip_while | fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ | `let after_invalid = utf8_chunks.skip_while( | c |
| take_while | fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ | `let valid_only = utf8_chunks.take_while( | c |
| map_while (с версии 1.57.0) | fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ | `let valid_strings = utf8_chunks.map_while( | c |
| skip | fn skip(self, n: usize) -> Skip<Self> ⓘ | let skipped = utf8_chunks.skip(2); | Создает итератор, который пропускает первые n элементов |
| take | fn take(self, n: usize) -> Take<Self> ⓘ | let taken = utf8_chunks.take(3); | Создает итератор, который выдает первые n элементов или меньше, если базовый итератор закончится раньше |
| scan | fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ | `let scanned = utf8_chunks.scan(0, | acc, chunk |
| flat_map | fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ | `let all_bytes = utf8_chunks.flat_map( | c |
| flatten (с версии 1.29.0) | fn flatten(self) -> Flatten<Self> ⓘ | let flattened = utf8_chunks.flatten(); | Создает итератор, который разглаживает вложенную структуру |
| map_windows | fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ | `let windows = utf8_chunks.map_windows( | arr: &[Utf8Chunk; 3] |
| fuse | fn fuse(self) -> Fuse<Self> ⓘ | let fused = utf8_chunks.fuse(); | Создает итератор, который завершается после первого None |
| inspect | fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ | `let inspected = utf8_chunks.inspect( | chunk |
| by_ref | fn by_ref(&mut self) -> &mut Self | utf8_chunks.by_ref().take(5).for_each(...); | Создает "по ссылке" адаптер для этого экземпляра Iterator |
| collect | fn collect<B>(self) -> B | let vec: Vec<Utf8Chunk> = utf8_chunks.collect(); | Преобразует итератор в коллекцию |
| try_collect | fn try_collect<B>(&mut self) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType | let result: Result<Vec<_>, _> = utf8_chunks.try_collect(); | 🔬 Ночная экспериментальная функция (iterator_try_collect #94047). Пытается преобразовать итератор в коллекцию, замыкаясь при первой ошибке |
| collect_into | fn collect_into<E>(self, collection: &mut E) -> &mut E | utf8_chunks.collect_into(&mut vec); | 🔬 Ночная экспериментальная функция (iter_collect_into #94780). Собирает все элементы из итератора в коллекцию |
| partition | fn partition<B, F>(self, f: F) -> (B, B) | `let (valid, invalid) = utf8_chunks.partition( | c |
| partition_in_place | fn partition_in_place<'a, T, P>(self, predicate: P) -> usize | `let true_count = utf8_chunks.partition_in_place( | c |
| is_partitioned | fn is_partitioned<P>(self, predicate: P) -> bool | `let partitioned = utf8_chunks.is_partitioned( | c |
| try_fold (с версии 1.27.0) | fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R | `let total_len = utf8_chunks.try_fold(0, | acc, chunk |
| try_for_each (с версии 1.27.0) | fn try_for_each<F, R>(&mut self, f: F) -> R | `utf8_chunks.try_for_each( | chunk |
| fold | fn fold<B, F>(self, init: B, f: F) -> B | `let total_valid_len = utf8_chunks.fold(0, | acc, chunk |
| reduce (с версии 1.51.0) | fn reduce<F>(self, f: F) -> Option<Self::Item> | `let largest_chunk = utf8_chunks.reduce( | a, b |
| try_reduce | fn try_reduce<R>(&mut self, f: impl FnMut(Self::Item, Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType | `let largest = utf8_chunks.try_reduce( | a, b |
| all | fn all<F>(&mut self, f: F) -> bool | `let all_valid = utf8_chunks.all( | c |
| any | fn any<F>(&mut self, f: F) -> bool | `let has_invalid = utf8_chunks.any( | c |
| find | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | `let first_invalid = utf8_chunks.find( | c |
| find_map (с версии 1.30.0) | fn find_map<B, F>(&mut self, f: F) -> Option<B> | `let first_invalid_bytes = utf8_chunks.find_map( | c |
| try_find | fn try_find<R>(&mut self, f: impl FnMut(&Self::Item) -> R) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType | `let result = utf8_chunks.try_find( | c |
| position | fn position<P>(&mut self, predicate: P) -> Option<usize> | `let pos = utf8_chunks.position( | c |
| rposition | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | `let rpos = utf8_chunks.rposition( | c |
| max | fn max(self) -> Option<Self::Item> | let max_chunk = utf8_chunks.max(); | Возвращает максимальный элемент итератора |
| min | fn min(self) -> Option<Self::Item> | let min_chunk = utf8_chunks.min(); | Возвращает минимальный элемент итератора |
| max_by_key (с версии 1.6.0) | fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let longest_valid = utf8_chunks.max_by_key( | c |
| max_by (с версии 1.15.0) | fn max_by<F>(self, compare: F) -> Option<Self::Item> | `let longest = utf8_chunks.max_by( | a, b |
| min_by_key (с версии 1.6.0) | fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> | `let shortest_valid = utf8_chunks.min_by_key( | c |
| min_by (с версии 1.15.0) | fn min_by<F>(self, compare: F) -> Option<Self::Item> | `let shortest = utf8_chunks.min_by( | a, b |
| rev | fn rev(self) -> Rev<Self> ⓘ | let reversed = utf8_chunks.rev(); | Меняет направление итератора на противоположное |
| unzip | fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) | `let (valids, invalids): (Vec<&str>, Vec<&[u8]>) = utf8_chunks.map( | c |
| copied (с версии 1.36.0) | fn copied<'a, T>(self) -> Copied<Self> ⓘ | let copied: Copied<_> = utf8_chunks.copied(); | Создает итератор, который копирует все свои элементы |
| cloned | fn cloned<'a, T>(self) -> Cloned<Self> ⓘ | let cloned: Cloned<_> = utf8_chunks.cloned(); | Создает итератор, который клонирует все свои элементы |
| cycle | fn cycle(self) -> Cycle<Self> ⓘ | let cycled = utf8_chunks.cycle(); | Повторяет итератор бесконечно |
| array_chunks | fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ | let chunks = utf8_chunks.array_chunks::<3>(); | 🔬 Ночная экспериментальная функция (iter_array_chunks #100450). Возвращает итератор по N элементам итератора за раз |
| sum (с версии 1.11.0) | fn sum<S>(self) -> S | `let total_len: usize = utf8_chunks.map( | c |
| product (с версии 1.11.0) | fn product<P>(self) -> P | `let product: usize = utf8_chunks.map( | c |
| cmp (с версии 1.5.0) | fn cmp<I>(self, other: I) -> Ordering | utf8_chunks.cmp(other_iter) | Лексикографически сравнивает элементы этого Iterator с элементами другого |
| cmp_by | fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering | `utf8_chunks.cmp_by(other_iter, | a, b |
| partial_cmp (с версии 1.5.0) | fn partial_cmp<I>(self, other: I) -> Option<Ordering> | utf8_chunks.partial_cmp(other_iter) | Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткое замыкание, возвращая результат без сравнения оставшихся элементов |
| partial_cmp_by | fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> | `utf8_chunks.partial_cmp_by(other_iter, | a, b |
| eq (с версии 1.5.0) | fn eq<I>(self, other: I) -> bool | utf8_chunks.eq(other_iter) | Определяет, равны ли элементы этого Iterator элементам другого |
| eq_by | fn eq_by<I, F>(self, other: I, eq: F) -> bool | `utf8_chunks.eq_by(other_iter, | a, b |
| ne (с версии 1.5.0) | fn ne<I>(self, other: I) -> bool | utf8_chunks.ne(other_iter) | Определяет, не равны ли элементы этого Iterator элементам другого |
| lt (с версии 1.5.0) | fn lt<I>(self, other: I) -> bool | utf8_chunks.lt(other_iter) | Определяет, являются ли элементы этого Iterator лексикографически меньше элементов другого |
| le (с версии 1.5.0) | fn le<I>(self, other: I) -> bool | utf8_chunks.le(other_iter) | Определяет, являются ли элементы этого Iterator лексикографически меньше или равны элементам другого |
| gt (с версии 1.5.0) | fn gt<I>(self, other: I) -> bool | utf8_chunks.gt(other_iter) | Определяет, являются ли элементы этого Iterator лексикографически больше элементов другого |
| ge (с версии 1.5.0) | fn ge<I>(self, other: I) -> bool | utf8_chunks.ge(other_iter) | Определяет, являются ли элементы этого Iterator лексикографически больше или равны элементам другого |
| is_sorted (с версии 1.82.0) | fn is_sorted(self) -> bool | let sorted = utf8_chunks.is_sorted(); | Проверяет, отсортированы ли элементы этого итератора |
| is_sorted_by (с версии 1.82.0) | fn is_sorted_by<F>(self, compare: F) -> bool | `let sorted = utf8_chunks.is_sorted_by( | a, b |
| is_sorted_by_key (с версии 1.82.0) | fn is_sorted_by_key<F, K>(self, f: F) -> bool | `let sorted = utf8_chunks.is_sorted_by_key( | c |
impl FusedIterator for Utf8Chunks<'_>
Этот трейт не имеет методов, но гарантирует, что после исчерпания итератор всегда будет возвращать None
Структура Utf8Error
#![allow(unused)] fn main() { pub struct Utf8Error { /* приватные поля */ } }
Ошибки, которые могут возникнуть при попытке интерпретировать последовательность u8 как строку.
Таким образом, семейство функций и методов from_utf8 как для String, так и для &str используют эту ошибку.
Примеры
Методы этого типа ошибок могут быть использованы для создания функциональности, аналогичной String::from_utf8_lossy, без выделения памяти в куче:
#![allow(unused)] fn main() { fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) { loop { match std::str::from_utf8(input) { Ok(valid) => { push(valid); break } Err(error) => { let (valid, after_valid) = input.split_at(error.valid_up_to()); unsafe { push(std::str::from_utf8_unchecked(valid)) } push("\u{FFFD}"); if let Some(invalid_sequence_length) = error.error_len() { input = &after_valid[invalid_sequence_length..] } else { break } } } } } }
Реализации трейтов
impl Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| valid_up_to (с версии 1.5.0, константная с 1.63.0) | pub const fn valid_up_to(&self) -> usize | let valid_len = error.valid_up_to(); | Возвращает индекс в данной строке, до которого была проверена валидность UTF-8. Это максимальный индекс такой, что from_utf8(&input[..index]) вернет Ok(_) |
| error_len (с версии 1.20.0, константная с 1.63.0) | pub const fn error_len(&self) -> Option<usize> | let error_len = error.error_len(); | Предоставляет дополнительную информацию о сбое: None - неожиданно достигнут конец входных данных. valid_up_to() находится в 1-3 байтах от конца входных данных. Если поток байтов (например, файл или сетевой сокет) декодируется по частям, это может быть валидный символ, чья UTF-8 последовательность байтов распределена по нескольким чанкам. Some(len) - встретился неожиданный байт. Предоставленная длина - это длина невалидной последовательности байтов, которая начинается с индекса, заданного valid_up_to(). Декодирование должно продолжиться после этой последовательности (после вставки U+FFFD REPLACEMENT CHARACTER) в случае потери при декодировании |
impl Clone for Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| clone | fn clone(&self) -> Utf8Error | let cloned_error = error.clone(); | Возвращает копию значения |
| clone_from | fn clone_from(&mut self, source: &Self) | error.clone_from(&other_error); | Выполняет копирующее присваивание из source |
impl Debug for Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{:?}", error); | Форматирует значение с помощью заданного форматтера |
impl Display for Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| fmt | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> | println!("{}", error); | Форматирует значение с помощью заданного форматтера |
impl Error for Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| source (с версии 1.30.0) | fn source(&self) -> Option<&(dyn Error + 'static)> | let source = error.source(); | Возвращает исходную причину этой ошибки, если таковая имеется |
| description | fn description(&self) -> &str | let desc = error.description(); | 👎 Устарело с версии 1.42.0: используйте реализацию Display или to_string() |
| cause | fn cause(&self) -> Option<&dyn Error> | let cause = error.cause(); | 👎 Устарело с версии 1.33.0: заменено на Error::source, который поддерживает downcasting |
| provide | fn provide<'a>(&'a self, request: &mut Request<'a>) | error.provide(&mut request); | 🔬 Ночная экспериментальная функция (error_generic_member_access #99301). Предоставляет доступ на основе типов к контексту, предназначенному для отчетов об ошибках |
impl PartialEq for Utf8Error
| Функция | Синтаксис | Пример | Назначение |
|---|---|---|---|
| eq | fn eq(&self, other: &Utf8Error) -> bool | if error1 == error2 { ... } | Проверяет равенство значений self и other, используется оператором == |
| ne | fn ne(&self, other: &Rhs) -> bool | if error1 != error2 { ... } | Проверяет неравенство. Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины |
impl Copy for Utf8Error
Этот трейт не имеет методов, но позволяет типу быть скопированным путем побитового копирования
impl Eq for Utf8Error
Этот трейт не имеет методов, но указывает, что тип реализует отношение эквивалентности (рефлексивность, симметричность, транзитивность)
impl StructuralPartialEq for Utf8Error
Этот трейт не имеет методов и используется для указания структурного равенства в макросах
Traits
Трейт FromStr
#![allow(unused)] fn main() { pub trait FromStr: Sized { type Err; // Обязательный метод fn from_str(s: &str) -> Result<Self, Self::Err>; } }
Парсинг значения из строки
Метод from_str трейта FromStr часто используется неявно через метод parse типа str. Примеры смотрите в документации к parse.
FromStr не имеет параметра времени жизни, поэтому можно парсить только типы, которые сами не содержат параметра времени жизни. Другими словами, можно распарсить i32 с помощью FromStr, но не &i32. Можно распарсить структуру, содержащую i32, но не ту, что содержит &i32.
Формат ввода и круговая конверсия (round-tripping)
Формат ввода, ожидаемый реализацией FromStr для типа, зависит от самого типа. Проверяйте документацию по конкретному типу для ознакомления с форматами ввода, которые он умеет парсить. Обратите внимание, что формат ввода реализации FromStr для типа может не обязательно принимать формат вывода его реализации Display. Даже если это так, реализация Display может не быть lossless (без потерь), поэтому круговая конверсия может потерять информацию.
Однако, если тип имеет lossless реализацию Display, вывод которой предназначен для удобного машинного парсинга, а не только для восприятия человеком, то тип может принимать тот же формат в FromStr, и это должно быть задокументировано. Наличие реализаций Display и FromStr, где результат Display нельзя распарсить с помощью FromStr, может удивить пользователей.
Примеры
Базовая реализация FromStr для примера типа Point:
#![allow(unused)] fn main() { use std::str::FromStr; #[derive(Debug, PartialEq)] struct Point { x: i32, y: i32 } #[derive(Debug, PartialEq, Eq)] struct ParsePointError; impl FromStr for Point { type Err = ParsePointError; fn from_str(s: &str) -> Result<Self, Self::Err> { let (x, y) = s .strip_prefix('(') .and_then(|s| s.strip_suffix(')')) .and_then(|s| s.split_once(',')) .ok_or(ParsePointError)?; let x_fromstr = x.parse::<i32>().map_err(|_| ParsePointError)?; let y_fromstr = y.parse::<i32>().map_err(|_| ParsePointError)?; Ok(Point { x: x_fromstr, y: y_fromstr }) } } let expected = Ok(Point { x: 1, y: 2 }); // Явный вызов assert_eq!(Point::from_str("(1,2)"), expected); // Неявные вызовы через parse assert_eq!("(1,2)".parse(), expected); assert_eq!("(1,2)".parse::<Point>(), expected); // Некорректная входная строка assert!(Point::from_str("(1 2)").is_err()); }
Связанные типы (Обязательные)
type Err
Связанный тип ошибки, который может быть возвращен при парсинге.
Обязательные методы
fn from_str(s: &str) -> Result<Self, Self::Err>
Парсит строку s, чтобы вернуть значение этого типа.
Если парсинг успешен, возвращает значение внутри Ok, в противном случае, когда строка имеет неправильный формат, возвращает ошибку, специфичную для внутренней части Err. Тип ошибки специфичен для реализации трейта.
Примеры
Базовое использование с i32 — типом, который реализует FromStr:
#![allow(unused)] fn main() { use std::str::FromStr; let s = "5"; let x = i32::from_str(s).unwrap(); assert_eq!(5, x); }
Совместимость с dyn (динамической диспетчеризацией)
Этот трейт не совместим с dyn.
В более старых версиях Rust совместимость с dyn называлась "объектной безопасностью" (object safety), поэтому этот трейт не является объектно-безопасным.
Реализации (Implementors)
| Тип | Назначение (реализации FromStr) |
|---|---|
IpAddr | Парсинг IP-адреса (IPv4 или IPv6) |
SocketAddr | Парсинг сетевого адреса (IP + порт) |
bool | Парсинг логического значения ("true"/"false") |
char | Парсинг одного Unicode символа |
f16 | Парсинг 16-битного числа с плавающей запятой |
f32 | Парсинг 32-битного числа с плавающей запятой |
f64 | Парсинг 64-битного числа с плавающей запятой |
i8 | Парсинг 8-битного целого числа со знаком |
i16 | Парсинг 16-битного целого числа со знаком |
i32 | Парсинг 32-битного целого числа со знаком |
i64 | Парсинг 64-битного целого числа со знаком |
i128 | Парсинг 128-битного целого числа со знаком |
isize | Парсинг целого числа со знаком размером с указатель |
u8 | Парсинг 8-битного целого числа без знака |
u16 | Парсинг 16-битного целого числа без знака |
u32 | Парсинг 32-битного целого числа без знака |
u64 | Парсинг 64-битного целого числа без знака |
u128 | Парсинг 128-битного целого числа без знака |
usize | Парсинг целого числа без знака размером с указатель |
ByteString | Парсинг байтовой строки |
CString | Парсинг строки, оканчивающейся нулем, для взаимодействия с C |
OsString | Парсинг строки, специфичной для платформы |
Ipv4Addr | Парсинг IPv4 адреса |
Ipv6Addr | Парсинг IPv6 адреса |
SocketAddrV4 | Парсинг IPv4 сетевого адреса (IPv4 + порт) |
SocketAddrV6 | Парсинг IPv6 сетевого адреса (IPv6 + порт) |
NonZero<i8> | Парсинг гарантированно ненулевого i8 |
NonZero<i16> | Парсинг гарантированно ненулевого i16 |
NonZero<i32> | Парсинг гарантированно ненулевого i32 |
NonZero<i64> | Парсинг гарантированно ненулевого i64 |
NonZero<i128> | Парсинг гарантированно ненулевого i128 |
NonZero<isize> | Парсинг гарантированно ненулевого isize |
NonZero<u8> | Парсинг гарантированно ненулевого u8 |
NonZero<u16> | Парсинг гарантированно ненулевого u16 |
NonZero<u32> | Парсинг гарантированно ненулевого u32 |
NonZero<u64> | Парсинг гарантированно ненулевого u64 |
NonZero<u128> | Парсинг гарантированно ненулевого u128 |
NonZero<usize> | Парсинг гарантированно ненулевого usize |
PathBuf | Парсинг пути в файловой системе |
String | Парсинг строки (фактически создание String из &str) |
Literal | Парсинг токена литерала (в контексте макросов/proc-macro) |
TokenStream | Парсинг потока токенов (в контексте макросов/proc-macro) |
Functions
Функция from_boxed_utf8_unchecked
Описание
#![allow(unused)] fn main() { pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> }
Преобразует размещённый в куче срез байтов в размещённый в куче строковый срез без проверки того, что строка содержит корректный UTF-8.
Безопасность
- Предоставленные байты должны содержать корректную последовательность UTF-8.
Примеры
#![allow(unused)] fn main() { let smile_utf8 = Box::new([226, 152, 186]); let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) }; assert_eq!("☺", &*smile); }
Функция from_utf8
Описание
#![allow(unused)] fn main() { pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> }
Преобразует срез байтов в строковый срез.
Это псевдоним для str::from_utf8.
Строковый срез (&str) состоит из байтов (u8), и срез байтов (&[u8]) также состоит из байтов, поэтому эта функция выполняет преобразование между ними. Однако не все срезы байтов являются корректными строковыми срезами: &str требует, чтобы данные были корректным UTF-8. from_utf8() проверяет, являются ли байты корректным UTF-8, и затем выполняет преобразование.
Если вы уверены, что срез байтов является корректным UTF-8, и не хотите тратить ресурсы на проверку валидности, существует небезопасная версия этой функции - from_utf8_unchecked, которая имеет такое же поведение, но пропускает проверку.
Если вам нужна String вместо &str, рассмотрите String::from_utf8.
Поскольку вы можете разместить [u8; N] в стеке и взять из него &[u8], эта функция является одним из способов получить строку, размещённую в стеке. Пример этого приведён в разделе примеров ниже.
Ошибки
Возвращает Err, если срез не является UTF-8, с описанием причины, почему предоставленный срез не является корректным UTF-8.
Примеры
Базовое использование:
#![allow(unused)] fn main() { use std::str; // несколько байтов в векторе let sparkle_heart = vec![240, 159, 146, 150]; // Мы можем использовать оператор ? (try) для проверки, являются ли байты корректными let sparkle_heart = str::from_utf8(&sparkle_heart)?; assert_eq!("💖", sparkle_heart); }
Некорректные байты:
#![allow(unused)] fn main() { use std::str; // несколько некорректных байтов в векторе let sparkle_heart = vec![0, 159, 146, 150]; assert!(str::from_utf8(&sparkle_heart).is_err()); }
Смотрите документацию Utf8Error для получения более подробной информации о типах ошибок, которые могут быть возвращены.
"Строка, размещённая в стеке":
#![allow(unused)] fn main() { use std::str; // несколько байтов в массиве, размещённом в стеке let sparkle_heart = [240, 159, 146, 150]; // Мы знаем, что эти байты корректны, поэтому просто используем `unwrap()`. let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap(); assert_eq!("💖", sparkle_heart); }
Некорректные байты:
#![allow(unused)] fn main() { use std::str; // несколько некорректных байтов в векторе let sparkle_heart = vec![0, 159, 146, 150]; assert!(str::from_utf8(&sparkle_heart).is_err()); }
Смотрите документацию Utf8Error для получения более подробной информации о типах ошибок, которые могут быть возвращены.
"Строка, размещённая в стеке":
#![allow(unused)] fn main() { use std::str; // несколько байтов в массиве, размещённом в стеке let sparkle_heart = [240, 159, 146, 150]; // Мы знаем, что эти байты корректны, поэтому просто используем `unwrap()`. let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap(); assert_eq!("💖", sparkle_heart); }
Функция from_utf8_mut
Описание
#![allow(unused)] fn main() { pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> }
Преобразует изменяемый срез байтов в изменяемый строковый срез.
Это псевдоним для str::from_utf8_mut.
Примеры
Базовое использование:
#![allow(unused)] fn main() { use std::str; // "Hello, Rust!" в виде изменяемого вектора let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33]; // Так как мы знаем, что эти байты корректны, мы можем использовать `unwrap()` let outstr = str::from_utf8_mut(&mut hellorust).unwrap(); assert_eq!("Hello, Rust!", outstr); }
Некорректные байты:
#![allow(unused)] fn main() { use std::str; // Некорректные байты в изменяемом векторе let mut invalid = vec![128, 223]; assert!(str::from_utf8_mut(&mut invalid).is_err()); }
Смотрите документацию Utf8Error для получения более подробной информации о типах ошибок, которые могут быть возвращены.
Некорректные байты:
#![allow(unused)] fn main() { use std::str; // Некорректные байты в изменяемом векторе let mut invalid = vec![128, 223]; assert!(str::from_utf8_mut(&mut invalid).is_err()); }
Смотрите документацию Utf8Error для получения более подробной информации о типах ошибок, которые могут быть возвращены.
Функция from_utf8_unchecked
Версия 1.0.0 (const: 1.55.0) · [Исходный код]
Описание
#![allow(unused)] fn main() { pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str }
Преобразует срез байтов в строковый срез без проверки того, что строка содержит корректный UTF-8.
Это псевдоним для str::from_utf8_unchecked.
Для получения дополнительной информации смотрите безопасную версию - from_utf8.
Безопасность
Переданные байты должны быть корректным UTF-8.
Примеры
Базовое использование:
#![allow(unused)] fn main() { use std::str; // несколько байтов в векторе let sparkle_heart = vec![240, 159, 146, 150]; let sparkle_heart = unsafe { str::from_utf8_unchecked(&sparkle_heart) }; assert_eq!("💖", sparkle_heart); }
Функция from_utf8_unchecked_mut
Версия 1.20.0 (const: 1.83.0) · [Исходный код]
Описание
#![allow(unused)] fn main() { pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str }
Преобразует срез байтов в строковый срез без проверки того, что строка содержит корректный UTF-8; изменяемая версия.
Это псевдоним для str::from_utf8_unchecked_mut.
Смотрите неизменяемую версию from_utf8_unchecked() для документации и требований безопасности.
Примеры
Базовое использование:
#![allow(unused)] fn main() { use std::str; let mut heart = vec![240, 159, 146, 150]; let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) }; assert_eq!("💖", heart); }
Функция from_raw_parts
Описание
#![allow(unused)] fn main() { pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str }
🔬 Это экспериментальный API, доступный только в ночных сборках. (#119206)
Создаёт &str из указателя и длины.
Байты, на которые указывает указатель, должны быть корректным UTF-8. Если это может быть не так, используйте str::from_utf8(slice::from_raw_parts(ptr, len)), который вернёт Err, если данные не являются корректным UTF-8.
Эта функция является строковым эквивалентом slice::from_raw_parts. Смотрите документацию этой функции для вопросов безопасности и примеров.
Изменяемая версия этой функции - from_raw_parts_mut.
Функция from_raw_parts_mut
Описание
#![allow(unused)] fn main() { pub const unsafe fn from_raw_parts_mut<'a>( ptr: *mut u8, len: usize, ) -> &'a mut str }
🔬 Это экспериментальный API, доступный только в ночных сборках. (#119206)
Создаёт &mut str из указателя и длины.
Байты, на которые указывает указатель, должны быть корректным UTF-8. Если это может быть не так, используйте str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len)), который вернёт Err, если данные не являются корректным UTF-8.
Эта функция является строковым эквивалентом slice::from_raw_parts_mut. Смотрите документацию этой функции для вопросов безопасности и примеров.
Неизменяемая версия этой функции - from_raw_parts.
Модуль string
Описание
UTF-8 кодированная, расширяемая строка.
Этот модуль содержит тип String, трейт ToString для преобразования в строки и несколько типов ошибок, которые могут возникнуть при работе со String.
Примеры
Создание строк
Есть несколько способов создать новую String из строкового литерала:
#![allow(unused)] fn main() { let s = "Hello".to_string(); let s = String::from("world"); let s: String = "also this".into(); }
Конкатенация строк
Вы можете создать новую String из существующей с помощью конкатенации с +:
#![allow(unused)] fn main() { let s = "Hello".to_string(); let message = s + " world!"; }
Преобразование из/в байты
Если у вас есть вектор валидных UTF-8 байт, вы можете создать из него String. Вы можете сделать и обратное преобразование.
#![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); let bytes = sparkle_heart.into_bytes(); assert_eq!(bytes, [240, 159, 146, 150]); }
Структуры
Drain
Итератор дренажа для String. Позволяет извлекать части строки.
FromUtf8Error
Возможное значение ошибки при преобразовании String из вектора UTF-8 байт.
FromUtf16Error
Возможное значение ошибки при преобразовании String из среза UTF-16 байт.
String
UTF-8 кодированная, расширяемая строка.
IntoChars ⚡️
Экспериментальный итератор по символам строки.
Трейты
ToString
Трейт для преобразования значения в String.
Псевдонимы типов
ParseError
Псевдоним типа для Infallible. Используется при парсинге строк.
Основные возможности
Создание строк
#![allow(unused)] fn main() { // Пустая строка let s = String::new(); // Из строкового литерала let s = String::from("hello"); // Из символа let s = String::from('c'); // Повторение символа let s = "a".repeat(5); // "aaaaa" }
Модификация строк
#![allow(unused)] fn main() { let mut s = String::from("foo"); // Добавление строки s.push_str("bar"); // Добавление символа s.push('!'); // Вставка строки s.insert_str(0, "start "); // Очистка s.clear(); }
Получение информации
#![allow(unused)] fn main() { let s = String::from("hello"); // Длина в байтах let len = s.len(); // 5 // Проверка на пустоту let is_empty = s.is_empty(); // false // Доступ к символам for c in s.chars() { println!("{}", c); } // Доступ к байтам for b in s.bytes() { println!("{}", b); } }
Сравнение строк
#![allow(unused)] fn main() { let s1 = String::from("hello"); let s2 = String::from("world"); assert!(s1 != s2); assert!(s1 == "hello"); }
Особенности UTF-8
Поскольку String всегда содержит валидные UTF-8 данные, индексация по байтам может быть небезопасной:
#![allow(unused)] fn main() { let s = String::from("hello"); // Получение среза (только если границы символов) let slice = &s[0..4]; // "hell" // Итерация по символам - безопасный способ for (i, c) in s.char_indices() { println!("{}: {}", i, c); } }
Производительность
String реализована как вектор байт (Vec<u8>) с гарантией валидности UTF-8:
- Быстрые операции добавления в конец
- Эффективное использование памяти
- Гарантия безопасности памяти
Распространенные ошибки
#![allow(unused)] fn main() { // НЕВЕРНО - индексация может привести к панике // let c = s[0]; // ВЕРНО - используйте итераторы if let Some(c) = s.chars().next() { println!("Первый символ: {}", c); } }
Модуль string предоставляет мощный и безопасный API для работы с текстовыми данными в Rust, сочетающий производительность с гарантиями безопасности типов.
Struct
Структура Drain<'a>
Описание
Итератор дренажа для String.
Эта структура создается методом drain для String. Смотрите его документацию для получения дополнительной информации.
Синтаксис
#![allow(unused)] fn main() { pub struct Drain<'a> { /* приватные поля */ } }
Методы
as_str
#![allow(unused)] fn main() { pub fn as_str(&self) -> &str }
Возвращает оставшуюся (под)строку этого итератора как срез.
Доступность: 1.55.0
Примеры
#![allow(unused)] fn main() { let mut s = String::from("abc"); let mut drain = s.drain(..); assert_eq!(drain.as_str(), "abc"); let _ = drain.next().unwrap(); assert_eq!(drain.as_str(), "bc"); }
Реализации трейтов
AsRef<[u8]> и AsRef<str>
#![allow(unused)] fn main() { impl<'a> AsRef<[u8]> for Drain<'a> impl<'a> AsRef<str> for Drain<'a> }
Позволяют преобразование в срез байт и строковый срез соответственно.
Debug
#![allow(unused)] fn main() { impl Debug for Drain<'_> }
Позволяет форматирование Drain для отладки.
DoubleEndedIterator
#![allow(unused)] fn main() { impl DoubleEndedIterator for Drain<'_> }
Реализует двустороннюю итерацию по символам строки.
Основные методы:
next_back()- удаляет и возвращает элемент с конца итератораnth_back()- возвращает n-й элемент с концаtry_rfold()- версияtry_foldс концаrfold()- сокращает элементы с концаrfind()- поиск с конца
Drop
#![allow(unused)] fn main() { impl Drop for Drain<'_> }
Реализует деструктор для Drain. При удалении итератора оставшаяся часть строки становится доступной.
Iterator
#![allow(unused)] fn main() { impl Iterator for Drain<'_> }
Реализует основную функциональность итератора.
Ассоциированный тип:
#![allow(unused)] fn main() { type Item = char }
Тип элементов, по которым происходит итерация - символы (char).
Основные методы:
next()- продвигает итератор и возвращает следующее значениеsize_hint()- возвращает границы оставшейся длины итератораlast()- возвращает последний элемент
Методы трансформации:
map()- преобразует элементыfilter()- фильтрует элементыtake()- берет первые n элементовskip()- пропускает первые n элементовenumerate()- добавляет счетчик итераций
Методы агрегации:
fold()- свертывает элементы в аккумуляторreduce()- сокращает элементы до одногоsum()- суммирует элементыproduct()- перемножает элементы
Методы поиска:
find()- ищет элемент по предикатуposition()- ищет позицию элементаall()- проверяет, все ли элементы удовлетворяют предикатуany()- проверяет, есть ли хотя бы один элемент, удовлетворяющий предикату
FusedIterator
#![allow(unused)] fn main() { impl FusedIterator for Drain<'_> }
Гарантирует, что после исчерпания итератор всегда будет возвращать None.
Send и Sync
#![allow(unused)] fn main() { impl Send for Drain<'_> impl Sync for Drain<'_> }
Drain может быть передан между потоками и использован из нескольких потоков.
Автоматические реализации трейтов
Freeze for Drain<'a>- может быть замороженRefUnwindSafe for Drain<'a>- безопасен для паникиUnpin for Drain<'a>- может быть безопасно перемещеноUnwindSafe for Drain<'a>- безопасен для паники
Примеры использования
Базовое использование
#![allow(unused)] fn main() { let mut s = String::from("hello world"); let mut drain = s.drain(2..7); assert_eq!(drain.next(), Some('l')); assert_eq!(drain.next(), Some('l')); assert_eq!(drain.next(), Some('o')); assert_eq!(drain.as_str(), " w"); // оставшаяся часть }
Дренаж с преобразованием
#![allow(unused)] fn main() { let mut s = String::from("123"); let collected: String = s.drain(..).collect(); assert_eq!(collected, "123"); assert_eq!(s, ""); // исходная строка опустошена }
Двусторонняя итерация
#![allow(unused)] fn main() { let mut s = String::from("abcd"); let mut drain = s.drain(..); assert_eq!(drain.next(), Some('a')); assert_eq!(drain.next_back(), Some('d')); assert_eq!(drain.next(), Some('b')); assert_eq!(drain.next_back(), Some('c')); assert_eq!(drain.next(), None); }
Особенности поведения
- При создании
Drainзаимствует исходную строку - Удаленные символы извлекаются из строки
- При удалении
Drainоставшаяся часть строки сдвигается - Итератор эффективно работает с UTF-8 символами
- Поддерживает произвольные диапазоны дренажа
Производительность
Drain обеспечивает эффективное удаление диапазона символов из строки без лишних аллокаций памяти, работая непосредственно с внутренним буфером String.
Структура FromUtf8Error
Описание
Возможное значение ошибки при преобразовании String из вектора UTF-8 байт.
Этот тип является типом ошибки для метода from_utf8 у String. Он разработан таким образом, чтобы тщательно избежать перераспределений памяти: метод into_bytes вернет вектор байт, который использовался в попытке преобразования.
Тип Utf8Error, предоставляемый std::str, представляет ошибку, которая может произойти при преобразовании среза u8 в &str. В этом смысле он является аналогом FromUtf8Error, и вы можете получить его из FromUtf8Error через метод utf8_error.
Синтаксис
#![allow(unused)] fn main() { pub struct FromUtf8Error { /* приватные поля */ } }
Методы
as_bytes
#![allow(unused)] fn main() { pub fn as_bytes(&self) -> &[u8] ⓘ }
Возвращает срез байт u8, которые пытались преобразовать в String.
Доступность: 1.26.0
Примеры
#![allow(unused)] fn main() { // некоторые невалидные байты в векторе let bytes = vec![0, 159]; let value = String::from_utf8(bytes); assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); }
into_utf8_lossy ⚡️
#![allow(unused)] fn main() { pub fn into_utf8_lossy(self) -> String }
Преобразует байты в String с потерями, заменяя невалидные UTF-8 последовательности символами замены.
Доступность: Экспериментальный API (только в ночных сборках)
Смотрите String::from_utf8_lossy для получения дополнительной информации о замене невалидных последовательностей и String::from_utf8_lossy_owned для функции String, которая соответствует этой функции.
Примеры
#![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(input).unwrap_or_else(|e| e.into_utf8_lossy()); assert_eq!(String::from("Hello �World"), output); }
into_bytes
#![allow(unused)] fn main() { pub fn into_bytes(self) -> Vec<u8> ⓘ }
Возвращает байты, которые пытались преобразовать в String.
Этот метод тщательно сконструирован, чтобы избежать аллокации. Он потребит ошибку, переместив байты, так что копия байт не должна быть создана.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { // некоторые невалидные байты в векторе let bytes = vec![0, 159]; let value = String::from_utf8(bytes); assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); }
utf8_error
#![allow(unused)] fn main() { pub fn utf8_error(&self) -> Utf8Error }
Получает Utf8Error для получения более подробной информации о неудаче преобразования.
Тип Utf8Error, предоставляемый std::str, представляет ошибку, которая может произойти при преобразовании среза u8 в &str. В этом смысле он является аналогом FromUtf8Error. Смотрите его документацию для получения более подробной информации об использовании.
Доступность: 1.0.0
Примеры
#![allow(unused)] fn main() { // некоторые невалидные байты в векторе let bytes = vec![0, 159]; let error = String::from_utf8(bytes).unwrap_err().utf8_error(); // первый байт невалиден здесь assert_eq!(1, error.valid_up_to()); }
Примеры использования
Базовое использование
#![allow(unused)] fn main() { // некоторые невалидные байты в векторе let bytes = vec![0, 159]; let value = String::from_utf8(bytes); assert!(value.is_err()); assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); }
Обработка ошибок с получением деталей
#![allow(unused)] fn main() { let invalid_bytes = vec![0xF0, 0x90, 0x80, 0x41]; // неполная UTF-8 последовательность match String::from_utf8(invalid_bytes) { Ok(string) => println!("Успешно: {}", string), Err(e) => { println!("Ошибка преобразования:"); println!("Байты: {:?}", e.as_bytes()); println!("Позиция ошибки: {}", e.utf8_error().valid_up_to()); println!("Возвращенные байты: {:?}", e.into_bytes()); } } }
Восстановление с потерями
#![allow(unused)] #![feature(string_from_utf8_lossy_owned)] fn main() { let corrupted = vec![b'H', b'e', b'l', b'l', b'o', 0xFF, b'W', b'o', b'r', b'l', b'd']; let result = String::from_utf8(corrupted) .unwrap_or_else(|e| e.into_utf8_lossy()); assert_eq!("Hello�World", result); }
Реализации трейтов
Clone
#![allow(unused)] fn main() { impl Clone for FromUtf8Error }
Позволяет клонирование FromUtf8Error.
Debug и Display
#![allow(unused)] fn main() { impl Debug for FromUtf8Error impl Display for FromUtf8Error }
Позволяют форматирование для отладки и пользовательского отображения.
Error
#![allow(unused)] fn main() { impl Error for FromUtf8Error }
Реализует трейт ошибки, позволяя использование в системах обработки ошибок.
PartialEq и Eq
#![allow(unused)] fn main() { impl PartialEq for FromUtf8Error impl Eq for FromUtf8Error }
Реализуют проверку на равенство для FromUtf8Error.
Автоматические реализации трейтов
Freeze for FromUtf8Error- может быть замороженRefUnwindSafe for FromUtf8Error- безопасен для паникиSend for FromUtf8Error- может быть передан между потокамиSync for FromUtf8Error- может быть разделен между потокамиUnpin for FromUtf8Error- может быть безопасно перемещеноUnwindSafe for FromUtf8Error- безопасен для паники
Особенности проектирования
- Эффективность памяти: избегает лишних аллокаций
- Информативность: предоставляет детальную информацию об ошибке
- Совместимость: интегрируется с системой ошибок Rust
- Гибкость: позволяет различные стратегии обработки ошибок
Использование в реальных сценариях
#![allow(unused)] fn main() { fn load_string_from_file(path: &str) -> Result<String, FromUtf8Error> { let bytes = std::fs::read(path).map_err(|_| { // В реальном коде здесь должна быть proper обработка ошибок FromUtf8Error { /* ... */ } })?; String::from_utf8(bytes) } // Использование match load_string_from_file("data.txt") { Ok(content) => println!("Содержимое: {}", content), Err(e) => { eprintln!("Ошибка загрузки файла: {}", e); eprintln!("Невалидные байты: {:?}", e.as_bytes()); } } }
Структура FromUtf16Error
Описание
Возможное значение ошибки при преобразовании String из среза UTF-16 байт.
Этот тип является типом ошибки для метода from_utf16 у String.
Синтаксис
#![allow(unused)] fn main() { pub struct FromUtf16Error(/* приватные поля */); }
Примеры
#![allow(unused)] fn main() { // 𝄞mu<invalid>ic let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063]; assert!(String::from_utf16(v).is_err()); }
Примеры использования
Базовое использование
#![allow(unused)] fn main() { // Валидная UTF-16 последовательность let valid_utf16: &[u16] = &[0x0048, 0x0065, 0x006C, 0x006C, 0x006F]; // "Hello" let result = String::from_utf16(valid_utf16); assert!(result.is_ok()); assert_eq!(result.unwrap(), "Hello"); // Невалидная UTF-16 последовательность (одиночный surrogate) let invalid_utf16: &[u16] = &[0xD800, 0x0061]; // одинокий high surrogate let result = String::from_utf16(invalid_utf16); assert!(result.is_err()); }
Обработка ошибок
#![allow(unused)] fn main() { fn process_utf16_data(data: &[u16]) -> Result<String, FromUtf16Error> { String::from_utf16(data) } let test_data = &[0xD834, 0xDD1E, 0x006D, 0x0075, 0xD800]; // невалидный surrogate match process_utf16_data(test_data) { Ok(string) => { println!("Успешно преобразовано: {}", string); } Err(e) => { println!("Ошибка преобразования UTF-16: {}", e); // К сожалению, FromUtf16Error не предоставляет методов для доступа к исходным данным // в отличие от FromUtf8Error } } }
Сравнение с FromUtf8Error
#![allow(unused)] fn main() { // FromUtf8Error предоставляет доступ к исходным байтам let utf8_bytes = vec![0xFF, 0xFE]; // невалидный UTF-8 if let Err(e) = String::from_utf8(utf8_bytes) { println!("Невалидные UTF-8 байты: {:?}", e.as_bytes()); } // FromUtf16Error не предоставляет аналогичных методов let utf16_data = &[0xD800]; // невалидный UTF-16 if let Err(e) = String::from_utf16(utf16_data) { println!("Ошибка UTF-16: {}", e); // Нет методов для доступа к исходным u16 данным } }
Реализации трейтов
Debug
#![allow(unused)] fn main() { impl Debug for FromUtf16Error }
Позволяет форматирование FromUtf16Error для отладки.
Пример
#![allow(unused)] fn main() { let invalid_data = &[0xD800]; let error = String::from_utf16(invalid_data).unwrap_err(); println!("Отладочная информация: {:?}", error); }
Display
#![allow(unused)] fn main() { impl Display for FromUtf16Error }
Позволяет пользовательское форматирование FromUtf16Error для отображения.
Пример
#![allow(unused)] fn main() { let invalid_data = &[0xD800]; let error = String::from_utf16(invalid_data).unwrap_err(); println!("Сообщение об ошибке: {}", error); }
Error
#![allow(unused)] fn main() { impl Error for FromUtf16Error }
Реализует трейт ошибки, позволяя использование в системах обработки ошибок Rust.
Методы:
source()- возвращает низкоуровневый источник этой ошибки, если естьdescription()- устаревший метод, используйте реализациюDisplaycause()- устаревший метод, заменен наError::sourceprovide()- экспериментальный метод для доступа к контексту ошибок
Пример использования в системе ошибок
#![allow(unused)] fn main() { use std::error::Error; fn handle_utf16_conversion(data: &[u16]) -> Result<(), Box<dyn Error>> { let _string = String::from_utf16(data)?; Ok(()) } let bad_data = &[0xD800]; if let Err(e) = handle_utf16_conversion(bad_data) { println!("Произошла ошибка: {}", e); if let Some(source) = e.source() { println!("Источник ошибки: {}", source); } } }
Автоматические реализации трейтов
Freeze for FromUtf16Error- может быть замороженRefUnwindSafe for FromUtf16Error- безопасен для паникиSend for FromUtf16Error- может быть передан между потокамиSync for FromUtf16Error- может быть разделен между потокамиUnpin for FromUtf16Error- может быть безопасно перемещеноUnwindSafe for FromUtf16Error- безопасен для паники
Особенности UTF-16
Валидные последовательности UTF-16
#![allow(unused)] fn main() { // Валидные символы BMP (Basic Multilingual Plane) let bmp_chars: &[u16] = &[0x0041, 0x0042, 0x0043]; // "ABC" assert!(String::from_utf16(bmp_chars).is_ok()); // Валидные surrogate пары для символов вне BMP let surrogate_pair: &[u16] = &[0xD834, 0xDD1E]; // музыкальный символ 𝄞 assert!(String::from_utf16(surrogate_pair).is_ok()); }
Невалидные последовательности UTF-16
#![allow(unused)] fn main() { // Одинокий high surrogate let lone_high: &[u16] = &[0xD800]; assert!(String::from_utf16(lone_high).is_err()); // Одинокий low surrogate let lone_low: &[u16] = &[0xDC00]; assert!(String::from_utf16(lone_low).is_err()); // Неправильный порядок surrogate let wrong_order: &[u16] = &[0xDD1E, 0xD834]; // low перед high assert!(String::from_utf16(wrong_order).is_err()); }
Практическое применение
Чтение данных из внешних источников
#![allow(unused)] fn main() { fn read_utf16_from_file(path: &str) -> Result<String, Box<dyn std::error::Error>> { use std::fs::File; use std::io::Read; let mut file = File::open(path)?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; // Предполагаем, что данные little-endian UTF-16 let u16_data: Vec<u16> = buffer .chunks_exact(2) .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) .collect(); String::from_utf16(&u16_data).map_err(|e| e.into()) } }
Обработка данных Windows API
#![allow(unused)] fn main() { #[cfg(windows)] fn get_windows_error_message() -> Result<String, FromUtf16Error> { use winapi::um::winbase::FormatMessageW; use winapi::um::winbase::FORMAT_MESSAGE_ALLOCATE_BUFFER; use winapi::um::winbase::FORMAT_MESSAGE_FROM_SYSTEM; use winapi::um::winbase::FORMAT_MESSAGE_IGNORE_INSERTS; use std::ptr; unsafe { let mut buffer: *mut u16 = ptr::null_mut(); let size = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, ptr::null_mut(), // код ошибки... 0, 0, &mut buffer as *mut *mut u16 as *mut u16, 0, ptr::null_mut() ); if size > 0 { let slice = std::slice::from_raw_parts(buffer, size as usize); let result = String::from_utf16(slice); // освобождение памяти... result } else { // обработка ошибки... } } } }
Ограничения
В отличие от FromUtf8Error, структура FromUtf16Error не предоставляет методов для доступа к исходным данным, которые вызвали ошибку. Это связано с тем, что метод from_utf16 принимает срез, а не владеющий вектор, поэтому нет возможности вернуть исходные данные.
Структура 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
Struct IntoChars
#![allow(unused)] fn main() { pub struct IntoChars { /* приватные поля */ } }
🔬 Экспериментальный API только для ночных сборок. (string_into_chars #133125)
Итератор по символам строки.
Этот структ создается методом into_chars у String. Для дополнительной информации смотрите его документацию.
Реализации
impl IntoChars
as_str
#![allow(unused)] fn main() { pub fn as_str(&self) -> &str }
🔬 Экспериментальный API только для ночных сборок. (string_into_chars #133125)
Представляет базовые данные как под-срез исходных данных.
Примеры
#![allow(unused)] #![feature(string_into_chars)] fn main() { let mut chars = String::from("abc").into_chars(); assert_eq!(chars.as_str(), "abc"); chars.next(); assert_eq!(chars.as_str(), "bc"); chars.next(); chars.next(); assert_eq!(chars.as_str(), ""); }
into_string
#![allow(unused)] fn main() { pub fn into_string(self) -> String }
🔬 Экспериментальный API только для ночных сборок. (string_into_chars #133125)
Потребляет IntoChars, возвращая оставшуюся строку.
Примеры
#![allow(unused)] #![feature(string_into_chars)] fn main() { let chars = String::from("abc").into_chars(); assert_eq!(chars.into_string(), "abc"); let mut chars = String::from("def").into_chars(); chars.next(); assert_eq!(chars.into_string(), "ef"); }
Реализации трейтов
impl Clone for IntoChars
clone
#![allow(unused)] fn main() { fn clone(&self) -> IntoChars ⓘ }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет присваивание-копирование из source.
impl Debug for IntoChars
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматировщика.
impl DoubleEndedIterator for IntoChars
next_back
#![allow(unused)] fn main() { fn next_back(&mut self) -> Option<char> }
Удаляет и возвращает элемент с конца итератора.
advance_back_by
#![allow(unused)] fn main() { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Экспериментальный API только для ночных сборок. (iter_advance_by #77404)
Перемещает итератор с конца на n элементов.
nth_back
#![allow(unused)] fn main() { fn nth_back(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент с конца итератора.
try_rfold
#![allow(unused)] fn main() { fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Обратная версия Iterator::try_fold(): принимает элементы, начиная с конца итератора.
rfold
#![allow(unused)] fn main() { fn rfold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Метод итератора, который сводит элементы итератора к единственному, конечному значению, начиная с конца.
rfind
#![allow(unused)] fn main() { fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора с конца, удовлетворяющий предикату.
impl Iterator for IntoChars
Item
#![allow(unused)] fn main() { type Item = char }
Тип элементов, по которым происходит итерация.
next
#![allow(unused)] fn main() { fn next(&mut self) -> Option<char> }
Перемещает итератор и возвращает следующее значение.
count
#![allow(unused)] fn main() { fn count(self) -> usize }
Потребляет итератор, подсчитывая количество итераций и возвращая его.
size_hint
#![allow(unused)] fn main() { fn size_hint(&self) -> (usize, Option<usize>) }
Возвращает границы оставшейся длины итератора.
last
#![allow(unused)] fn main() { fn last(self) -> Option<char> }
Потребляет итератор, возвращая последний элемент.
next_chunk
#![allow(unused)] fn main() { fn next_chunk<const N: usize>( &mut self, ) -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized, }
🔬 Экспериментальный API только для ночных сборок. (iter_next_chunk #98326)
Перемещает итератор и возвращает массив, содержащий следующие N значений.
advance_by
#![allow(unused)] fn main() { fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> }
🔬 Экспериментальный API только для ночных сборок. (iter_advance_by #77404)
Перемещает итератор на n элементов.
nth
#![allow(unused)] fn main() { fn nth(&mut self, n: usize) -> Option<Self::Item> }
Возвращает n-й элемент итератора.
step_by
#![allow(unused)] fn main() { fn step_by(self, step: usize) -> StepBy<Self> ⓘ where Self: Sized, }
Создает итератор, начинающийся с той же точки, но с шагом на заданное количество при каждой итерации.
step_by
#![allow(unused)] fn main() { fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator<Item = Self::Item>, }
Берет два итератора и создает новый итератор, проходящий по обоим последовательно.
zip
#![allow(unused)] fn main() { fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> ⓘ where Self: Sized, U: IntoIterator, }
'Объединяет' два итератора в один итератор пар.
intersperse
#![allow(unused)] fn main() { fn intersperse(self, separator: Self::Item) -> Intersperse<Self> ⓘ where Self: Sized, Self::Item: Clone, }
🔬 Экспериментальный API только для ночных сборок. (iter_intersperse #79524)
Создает новый итератор, который помещает копию separator между соседними элементами исходного итератора.
intersperse_with
#![allow(unused)] fn main() { fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> ⓘ where Self: Sized, G: FnMut() -> Self::Item, }
🔬 Экспериментальный API только для ночных сборок. (iter_intersperse #79524)
Создает новый итератор, который помещает элемент, сгенерированный separator, между соседними элементами исходного итератора.
map
#![allow(unused)] fn main() { fn map<B, F>(self, f: F) -> Map<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> B, }
Принимает замыкание и создает итератор, который вызывает это замыкание для каждого элемента.
for_each
#![allow(unused)] fn main() { fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), }
Вызывает замыкание для каждого элемента итератора.
filter
#![allow(unused)] fn main() { fn filter<P>(self, predicate: P) -> Filter<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который использует замыкание для определения, должен ли элемент быть выдан.
filter_map
#![allow(unused)] fn main() { fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> ⓘ where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно фильтрует и преобразует.
enumerate
#![allow(unused)] fn main() { fn enumerate(self) -> Enumerate<Self> ⓘ where Self: Sized, }
Создает итератор, который дает текущий счетчик итерации, а также следующее значение.
peekable
#![allow(unused)] fn main() { fn peekable(self) -> Peekable<Self> ⓘ where Self: Sized, }
Создает итератор, который может использовать методы peek и peek_mut для просмотра следующего элемента итератора без его потребления. Смотрите их документацию для дополнительной информации.
skip_while
#![allow(unused)] fn main() { fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который пропускает элементы на основе предиката.
take_while
#![allow(unused)] fn main() { fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> ⓘ where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Создает итератор, который выдает элементы на основе предиката.
map_while
#![allow(unused)] fn main() { fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> ⓘ where Self: Sized, P: FnMut(Self::Item) -> Option<B>, }
Создает итератор, который одновременно выдает элементы на основе предиката и преобразует.
skip
#![allow(unused)] fn main() { fn skip(self, n: usize) -> Skip<Self> ⓘ where Self: Sized, }
Создает итератор, который пропускает первые n элементов.
take
#![allow(unused)] fn main() { fn take(self, n: usize) -> Take<Self> ⓘ where Self: Sized, }
Создает итератор, который выдает первые n элементов, или меньше, если базовый итератор закончится раньше.
scan
#![allow(unused)] fn main() { fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> ⓘ where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>, }
Адаптер итератора, который, как и fold, хранит внутреннее состояние, но, в отличие от fold, создает новый итератор.
flat_map
#![allow(unused)] fn main() { fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> ⓘ where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U, }
Создает итератор, который работает как map, но уплощает вложенную структуру.
flatten
#![allow(unused)] fn main() { fn flatten(self) -> Flatten<Self> ⓘ where Self: Sized, Self::Item: IntoIterator, }
Создает итератор, который уплощает вложенную структуру.
map_windows
#![allow(unused)] fn main() { fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> ⓘ where Self: Sized, F: FnMut(&[Self::Item; N]) -> R, }
🔬 Экспериментальный API только для ночных сборок. (iter_map_windows #87155)
Вызывает заданную функцию f для каждого смежного окна размера N над self и возвращает итератор по результатам f. Как и в slice::windows(), окна при отображении также перекрываются. [Подробнее](Read more)
fuse
#![allow(unused)] fn main() { fn fuse(self) -> Fuse<Self> ⓘ where Self: Sized, }
Создает итератор, который заканчивается после первого None.
inspect
#![allow(unused)] fn main() { fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ where Self: Sized, F: FnMut(&Self::Item), }
Делает что-то с каждым элементом итератора, передавая значение дальше.
by_ref
#![allow(unused)] fn main() { fn by_ref(&mut self) -> &mut Self where Self: Sized, }
Создает адаптер "по ссылке" для этого экземпляра Iterator.
collect
#![allow(unused)] fn main() { fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized, }
Преобразует итератор в коллекцию.
try_collect
#![allow(unused)] fn main() { fn try_collect<B>( &mut self, ) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>, }
🔬 Экспериментальный API только для ночных сборок. (iterator_try_collect #94047)
Преобразует итератор в коллекцию с возможностью ошибки, прекращая работу при встрече с ошибкой.
collect_into
#![allow(unused)] fn main() { fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized, }
🔬 Экспериментальный API только для ночных сборок. (iter_collect_into #94780)
Собирает все элементы из итератора в коллекцию.
partition
#![allow(unused)] fn main() { fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool, }
Потребляет итератор, создавая две коллекции из него.
partition_in_place
#![allow(unused)] fn main() { fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool, }
🔬 Экспериментальный API только для ночных сборок. (iter_partition_in_place #62543)
Переупорядочивает элементы этого итератора на месте согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false. Возвращает количество найденных элементов true.
is_partitioned
#![allow(unused)] fn main() { fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool, }
🔬 Экспериментальный API только для ночных сборок. (iter_is_partitioned #62544)
Проверяет, разделены ли элементы этого итератора согласно заданному предикату, так что все элементы, возвращающие true, предшествуют всем элементам, возвращающим false.
try_fold
#![allow(unused)] fn main() { fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>, }
Метод итератора, который применяет функцию до тех пор, пока она возвращает успех, производя единственное, конечное значение.
try_for_each
#![allow(unused)] fn main() { fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>, }
Метод итератора, который применяет функцию с возможностью ошибки к каждому элементу в итераторе, останавливаясь при первой ошибке и возвращая эту ошибку.
fold
#![allow(unused)] fn main() { fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, }
Сворачивает каждый элемент в аккумулятор путем применения операции, возвращая конечный результат.
reduce
#![allow(unused)] fn main() { fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, }
Сводит элементы к одному, повторно применяя операцию свертки.
try_reduce
#![allow(unused)] fn main() { fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType where Self: Sized, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Экспериментальный API только для ночных сборок. (iterator_try_reduce #87053)
Сводит элементы к одному путем повторного применения операции свертки. Если замыкание возвращает ошибку, ошибка немедленно передается обратно вызывающей стороне.
all
#![allow(unused)] fn main() { fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли каждый элемент итератора предикату.
any
#![allow(unused)] fn main() { fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, }
Проверяет, соответствует ли любой элемент итератора предикату.
find
#![allow(unused)] fn main() { fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, }
Ищет элемент итератора, удовлетворяющий предикату.
find_map
#![allow(unused)] fn main() { fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, }
Применяет функцию к элементам итератора и возвращает первый не-None результат.
try_find
#![allow(unused)] fn main() { fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType where Self: Sized, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>>, }
🔬 Экспериментальный API только для ночных сборок. (try_find #63178)
Применяет функцию к элементам итератора и возвращает первый истинный результат или первую ошибку.
position
#![allow(unused)] fn main() { fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, }
Ищет элемент в итераторе, возвращая его индекс.
rposition
#![allow(unused)] fn main() { fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator, }
Ищет элемент в итераторе справа, возвращая его индекс.
max
#![allow(unused)] fn main() { fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает максимальный элемент итератора.
min
#![allow(unused)] fn main() { fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord, }
Возвращает минимальный элемент итератора.
max_by_key
#![allow(unused)] fn main() { fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает максимальное значение от указанной функции.
max_by
#![allow(unused)] fn main() { fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает максимальное значение по отношению к указанной функции сравнения.
min_by_key
#![allow(unused)] fn main() { fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B, }
Возвращает элемент, который дает минимальное значение от указанной функции.
min_by
#![allow(unused)] fn main() { fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, }
Возвращает элемент, который дает минимальное значение по отношению к указанной функции сравнения.
rev
#![allow(unused)] fn main() { fn rev(self) -> Rev<Self> ⓘ where Self: Sized + DoubleEndedIterator, }
Меняет направление итератора на противоположное.
unzip
#![allow(unused)] fn main() { fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>, }
Преобразует итератор пар в пару контейнеров.
copied
#![allow(unused)] fn main() { fn copied<'a, T>(self) -> Copied<Self> ⓘ where T: Copy + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который копирует все свои элементы.
cloned
#![allow(unused)] fn main() { fn cloned<'a, T>(self) -> Cloned<Self> ⓘ where T: Clone + 'a, Self: Sized + Iterator<Item = &'a T>, }
Создает итератор, который клонирует все свои элементы.
cycle
#![allow(unused)] fn main() { fn cycle(self) -> Cycle<Self> ⓘ where Self: Sized + Clone, }
Бесконечно повторяет итератор.
array_chunks
#![allow(unused)] fn main() { fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> ⓘ where Self: Sized, }
🔬 Экспериментальный API только для ночных сборок. (iter_array_chunks #100450)
Возвращает итератор по N элементам итератора за раз.
sum
#![allow(unused)] fn main() { fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>, }
Суммирует элементы итератора.
product
#![allow(unused)] fn main() { fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>, }
cmp
#![allow(unused)] fn main() { fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, }
Лексикографически сравнивает элементы этого Iterator с элементами другого.
cmp_by
#![allow(unused)] fn main() { fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering, }
🔬 Экспериментальный API только для ночных сборок. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
partial_cmp
#![allow(unused)] fn main() { fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Лексикографически сравнивает элементы PartialOrd этого Iterator с элементами другого. Сравнение работает как короткозамкнутое вычисление, возвращая результат без сравнения оставшихся элементов. Как только порядок может быть определен, вычисление останавливается и возвращается результат.
partial_cmp_by
#![allow(unused)] fn main() { fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>, }
🔬 Экспериментальный API только для ночных сборок. (iter_order_by #64295)
Лексикографически сравнивает элементы этого Iterator с элементами другого относительно указанной функции сравнения.
eq
#![allow(unused)] fn main() { fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, равны ли элементы этого Iterator элементам другого.
eq_by
#![allow(unused)] fn main() { fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool, }
🔬 Экспериментальный API только для ночных сборок. (iter_order_by #64295)
Определяет, равны ли элементы этого Iterator элементам другого относительно указанной функции равенства.
ne
#![allow(unused)] fn main() { fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, не равны ли элементы этого Iterator элементам другого.
lt
#![allow(unused)] fn main() { fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, являются ли элементы этого Iterator лексикографически меньшими, чем элементы другого.
le
#![allow(unused)] fn main() { fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, являются ли элементы этого Iterator лексикографически меньшими или равными элементам другого.
gt
#![allow(unused)] fn main() { fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, являются ли элементы этого Iterator лексикографически большими, чем элементы другого.
ge
#![allow(unused)] fn main() { fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized, }
Определяет, являются ли элементы этого Iterator лексикографически большими или равными элементам другого.
is_sorted
#![allow(unused)] fn main() { fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора.
is_sorted_by
#![allow(unused)] fn main() { fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции-компаратора.
is_sorted_by_key
#![allow(unused)] fn main() { fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd, }
Проверяет, отсортированы ли элементы этого итератора с использованием заданной функции извлечения ключа.
impl FusedIterator for IntoChars
Автоматические реализации трейтов
#![allow(unused)] fn main() { impl Freeze for IntoChars impl RefUnwindSafe for IntoChars impl Send for IntoChars impl Sync for IntoChars impl Unpin for IntoChars impl UnwindSafe for IntoChars }
Blanket Реализации
#![allow(unused)] fn main() { impl<T> Any for T where T: 'static + ?Sized, }
#![allow(unused)] fn main() { impl<T> Borrow<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> BorrowMut<T> for T where T: ?Sized, }
#![allow(unused)] fn main() { impl<T> CloneToUninit for T where T: Clone, }
#![allow(unused)] fn main() { impl<T> From<T> for T }
#![allow(unused)] fn main() { impl<T, U> Into<U> for T where U: From<T>, }
#![allow(unused)] fn main() { impl<I> IntoIterator for I where I: Iterator, }
#![allow(unused)] fn main() { impl<T> ToOwned for T where T: Clone, }
#![allow(unused)] fn main() { impl<T, U> TryFrom<U> for T where U: Into<T>, }
#![allow(unused)] fn main() { impl<T, U> TryInto<U> for T where U: TryFrom<T>, }
Type Alias
Type Alias ParseError
#![allow(unused)] fn main() { pub type ParseError = Infallible; }
Псевдоним типа для Infallible.
Этот псевдоним существует для обратной совместимости и может быть в конечном итоге устаревшим.
Псевдоним типа
#![allow(unused)] fn main() { pub enum ParseError {} }
Реализации трейтов
impl Clone for Infallible
clone
#![allow(unused)] fn main() { fn clone(&self) -> Infallible }
Возвращает копию значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
Выполняет присваивание-копирование из source.
impl Debug for Infallible
fmt
#![allow(unused)] fn main() { fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматировщика.
impl Display for Infallible
fmt
#![allow(unused)] fn main() { fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), Error> }
Форматирует значение с помощью заданного форматировщика.
impl Error for Infallible
source
#![allow(unused)] fn main() { fn source(&self) -> Option<&(dyn Error + 'static)> }
Возвращает низкоуровневую причину этой ошибки, если таковая имеется.
description
#![allow(unused)] fn main() { fn description(&self) -> &str }
👎Устарело начиная с версии 1.42.0: используйте реализацию Display или to_string()
cause
#![allow(unused)] fn main() { fn cause(&self) -> Option<&dyn Error> }
👎Устарело начиная с версии 1.33.0: заменено на Error::source, который поддерживает понижающее приведение типов
provide
#![allow(unused)] fn main() { fn provide<'a>(&'a self, request: &mut Request<'a>) }
🔬Экспериментальный API только для ночных сборок. (error_generic_member_access #99301)
Обеспечивает доступ на основе типов к контексту, предназначенному для отчетов об ошибках.
impl From<!> for Infallible
from
#![allow(unused)] fn main() { fn from(x: !) -> Infallible }
Преобразует в этот тип из входного типа.
impl Hash for Infallible
hash
#![allow(unused)] fn main() { fn hash<H>(&self, _: &mut H) where H: Hasher, }
Вводит это значение в заданный Hasher.
hash_slice
#![allow(unused)] fn main() { fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher, Self: Sized, }
Вводит срез этого типа в заданный Hasher.
impl Ord for Infallible
cmp
#![allow(unused)] fn main() { fn cmp(&self, _other: &Infallible) -> Ordering }
Этот метод возвращает Ordering между self и other.
max
#![allow(unused)] fn main() { fn max(self, other: Self) -> Self where Self: Sized, }
Сравнивает и возвращает максимальное из двух значений.
min
#![allow(unused)] fn main() { fn min(self, other: Self) -> Self where Self: Sized, }
Сравнивает и возвращает минимальное из двух значений.
clamp
#![allow(unused)] fn main() { fn clamp(self, min: Self, max: Self) -> Self where Self: Sized, }
Ограничивает значение определенным интервалом.
impl PartialEq for Infallible
eq
#![allow(unused)] fn main() { fn eq(&self, _: &Infallible) -> bool }
Проверяет, равны ли значения self и other, используется оператором ==.
ne
#![allow(unused)] fn main() { fn ne(&self, other: &Rhs) -> bool }
Проверяет на неравенство (!=). Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины.
impl PartialOrd for Infallible
partial_cmp
#![allow(unused)] fn main() { fn partial_cmp(&self, _other: &Infallible) -> Option<Ordering> }
Этот метод возвращает порядок между значениями self и other, если он существует. [Подробнее](Read more)
lt
#![allow(unused)] fn main() { fn lt(&self, other: &Rhs) -> bool }
Проверяет, меньше ли (self < other), используется оператором <. [Подробнее](Read more)
le
#![allow(unused)] fn main() { fn le(&self, other: &Rhs) -> bool }
Проверяет, меньше или равно (self <= other), используется оператором <=. [Подробнее](Read more)
gt
#![allow(unused)] fn main() { fn gt(&self, other: &Rhs) -> bool }
Проверяет, больше ли (self > other), используется оператором >. [Подробнее](Read more)
ge
#![allow(unused)] fn main() { fn ge(&self, other: &Rhs) -> bool }
Проверяет, больше или равно (self >= other), используется оператором >=. [Подробнее](Read more)
impl Termination for Infallible
report
#![allow(unused)] fn main() { fn report(self) -> ExitCode }
Вызывается для получения представления значения в виде кода статуса. Этот код статуса возвращается операционной системе.
impl Copy for Infallible
impl Eq for Infallible
Traits
Trait ToString
#![allow(unused)] fn main() { pub trait ToString { // Обязательный метод fn to_string(&self) -> String; } }
Трейт для преобразования значения в String.
Этот трейт автоматически реализуется для любого типа, который реализует трейт Display. Таким образом, ToString не должен реализовываться напрямую: вместо этого следует реализовать Display, и вы получите реализацию ToString бесплатно.
Обязательные методы
to_string
#![allow(unused)] fn main() { fn to_string(&self) -> String }
Преобразует данное значение в String.
Примеры
#![allow(unused)] fn main() { let i = 5; let five = String::from("5"); assert_eq!(five, i.to_string()); }
Реализаторы
ToString
#![allow(unused)] fn main() { impl<T> ToString for T where T: Display + ?Sized, }
Паники
В этой реализации метод to_string вызывает панику, если реализация Display возвращает ошибку. Это указывает на некорректную реализацию Display, поскольку fmt::Write для String никогда не возвращает ошибку самостоятельно.
Модуль sync
Полезные примитивы синхронизации.
Необходимость синхронизации
Концептуально, программа на Rust - это серия операций, которые будут выполнены на компьютере. Временная шкала событий, происходящих в программе, согласуется с порядком операций в коде.
Рассмотрим следующий код, работающий с некоторыми глобальными статическими переменными:
// FIXME(static_mut_refs): Не разрешать линт `static_mut_refs` #![allow(static_mut_refs)] static mut A: u32 = 0; static mut B: u32 = 0; static mut C: u32 = 0; fn main() { unsafe { A = 3; B = 4; A = A + B; C = B; println!("{A} {B} {C}"); C = A; } }
Кажется, что некоторые переменные, хранящиеся в памяти, изменяются, выполняется сложение, результат сохраняется в A, а переменная C изменяется дважды.
Когда задействован только один поток, результаты ожидаемы: выводится строка 7 4 4.
Что касается того, что происходит за кулисами, при включённых оптимизациях итоговый сгенерированный машинный код может сильно отличаться от кода:
- Первое сохранение в C может быть перемещено перед сохранением в A или B, как если бы мы написали
C = 4; A = 3; B = 4. - Присваивание A + B в A может быть удалено, поскольку сумма может храниться во временном местоположении до вывода, а глобальная переменная никогда не обновляется.
- Конечный результат может быть определён просто просмотром кода во время компиляции, поэтому свёртка констант может превратить весь блок в простой
println!("7 4 4").
Компилятору разрешено выполнять любую комбинацию этих оптимизаций, пока итоговый оптимизированный код при выполнении даёт те же результаты, что и без оптимизаций.
Из-за параллелизма, присущего современным компьютерам, предположения о порядке выполнения программы часто неверны. Доступ к глобальным переменным может приводить к недетерминированным результатам, даже если оптимизации компилятора отключены, и всё ещё возможно внесение ошибок синхронизации.
Заметьте, что благодаря гарантиям безопасности Rust, доступ к глобальным (static) переменным требует небезопасного кода, при условии, что мы не используем никакие примитивы синхронизации из этого модуля.
Неупорядоченное выполнение
Инструкции могут выполняться в порядке, отличном от определённого нами, по разным причинам:
- Переупорядочивание инструкций компилятором: Если компилятор может выдать инструкцию в более ранней точке, он попытается это сделать. Например, он может поднять загрузки памяти в начало блока кода, чтобы CPU мог начать предварительную выборку значений из памяти.
- В однопоточных сценариях это может вызывать проблемы при написании обработчиков сигналов или определённых видов низкоуровневого кода. Используйте барьеры компилятора для предотвращения этого переупорядочивания.
- Выполнение инструкций одним процессором вне порядка: Современные CPU способны к суперскалярному выполнению, т.е. несколько инструкций могут выполняться одновременно, даже though машинный код описывает последовательный процесс.
- Этот вид переупорядочивания прозрачно обрабатывается CPU.
- Многопроцессорная система, выполняющая несколько аппаратных потоков одновременно: В многопоточных сценариях вы можете использовать два вида примитивов для работы с синхронизацией:
- Барьеры памяти для обеспечения того, что обращения к памяти становятся видимыми другим CPU в правильном порядке.
- Атомарные операции для обеспечения того, что одновременный доступ к одному и тому же местоположению памяти не приводит к неопределённому поведению.
Высокоуровневые объекты синхронизации
Большинство низкоуровневых примитивов синхронизации довольно подвержены ошибкам и неудобны в использовании, поэтому стандартная библиотека также предоставляет некоторые высокоуровневые объекты синхронизации.
Эти абстракции могут быть построены из низкоуровневых примитивов. Для эффективности, объекты синхронизации в стандартной библиотеке обычно реализуются с помощью ядра операционной системы, которое может перепланировать потоки, пока они заблокированы на захвате блокировки.
Ниже приведён обзор доступных объектов синхронизации:
- Arc: Атомарно подсчитываемая ссылка (Atomically Reference-Counted pointer), которая может использоваться в многопоточных средах для продления времени жизни некоторых данных, пока все потоки не закончат их использование.
- Barrier: Обеспечивает ожидание несколькими потоками друг друга для достижения точки в программе перед продолжением выполнения все вместе.
- Condvar: Условная переменная (Condition Variable), предоставляющая возможность блокировать поток в ожидании наступления события.
- mpsc: Очереди с несколькими производителями и одним потребителем (Multi-producer, single-consumer), используемые для общения на основе сообщений. Могут предоставлять лёгкий механизм межпоточной синхронизации ценой дополнительной памяти.
- mpmc: Очереди с несколькими производителями и несколькими потребителями (Multi-producer, multi-consumer), используемые для общения на основе сообщений. Могут предоставлять лёгкий механизм межпоточной синхронизации ценой дополнительной памяти.
- Mutex: Механизм взаимного исключения (Mutual Exclusion), который обеспечивает, что не более одного потока в данный момент времени может обращаться к некоторым данным.
- Once: Используется для потокобезопасной однократной глобальной инициализации. В основном полезен для реализации других типов, таких как OnceLock.
- OnceLock: Используется для потокобезопасной однократной инициализации переменной с потенциально разными инициализаторами в зависимости от вызывающей стороны.
- LazyLock: Используется для потокобезопасной однократной инициализации переменной с использованием одной нульарной функции инициализации, предоставленной при создании.
- RwLock: Предоставляет механизм взаимного исключения, который позволяет нескольким читателям одновременно, while позволяя только одному писателю за раз. В некоторых случаях это может быть эффективнее мьютекса.
Модули
- atomic
- Атомарные типы
- mpsc
- Примитивы общения через очередь FIFO с несколькими производителями и одним потребителем
- mpmc Experimental
- Примитивы общения через очередь FIFO с несколькими производителями и несколькими потребителями
- nonpoison Experimental
- Синхронные блокировки без отравления
- poison Experimental
- Объекты синхронизации, использующие отравление
Многопоточность с поддержкой владения
Традиционно одновременный доступ к данным из нескольких потоков в Rust решается с помощью примитивов синхронизации, которые несут ответственность за синхронизацию доступа к данным, в отличие от передачи данных между потоками (как в каналах).
Модуль std::sync содержит следующие основные примитивы:
Arc: Потокобезопасный счетчик ссылок с атомарными операциямиMutex: Механизм взаимного исключения, обеспечивающий эксклюзивный доступ к даннымRwLock: Примитив "чтение-запись", позволяющий множественное чтение или эксклюзивную записьBarrier: Обеспечивает точку синхронизации, где multiple threads will wait for all to reachCondvar: Условная переменная для блокировки и пробуждения потоковOnce: Однократная инициализация для глобальных значенийmpsc: Многопоточные каналы "multiple-producer, single-consumer"atomic: Атомарные типы и операции
Многие примитивы синхронизации построены на основе атомарных операций, которые также доступны в этом модуле через подмодуль atomic. Атомарные типы представляют собой строительные блоки для примитивов синхронизации без блокировок и являются основой для всего многопоточного программирования в Rust.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; let data = Arc::new(Mutex::new(0)); let mut handles = vec![]; for _ in 0..10 { let data = Arc::clone(&data); let handle = thread::spawn(move || { let mut data = data.lock().unwrap(); *data += 1; }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } assert_eq!(*data.lock().unwrap(), 10); }
Структуры
Arc- Потокобезопасный указатель с подсчётом ссылок. «Arc» означает «Atomically Reference Counted» (Атомарно Подсчитываемая Ссылка).Barrier- Барьер позволяет нескольким потокам синхронизировать начало некоторого вычисления.BarrierWaitResult- BarrierWaitResult возвращается методом Barrier::wait(), когда все потоки в Barrier встретились.Condvar- Условная переменная.LazyLock- Значение, которое инициализируется при первом доступе.Mutex- Примитив взаимного исключения, полезный для защиты общих данных.MutexGuard- RAII-реализация «scoped lock» (блокировки с ограниченной областью видимости) мьютекса. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята.Once- Низкоуровневый примитив синхронизации для однократного глобального выполнения.OnceLock- Примитив синхронизации, который номинально может быть записан только один раз.OnceState- Состояние, передаваемое в параметр замыкания Once::call_once_force(). Состояние может использоваться для запроса статуса отравления Once.PoisonError- Тип ошибки, который может возвращаться при захвате блокировки.RwLock- Читательско-писательская блокировка.RwLockReadGuard- RAII-структура, используемая для освобождения общего доступа на чтение блокировки при удалении.RwLockWriteGuard- RAII-структура, используемая для освобождения эксклюзивного доступа на запись блокировки при удалении.WaitTimeoutResult- Тип, указывающий, вернулась ли timed wait (ожидание с таймаутом) на условной переменной из-за таймаута или нет.Weak- Weak - это версия Arc, которая содержит невладеющую ссылку на управляемое выделение памяти.- [
Exclusive] - Experimental Exclusive предоставляет только изменяемый доступ, также называемый эксклюзивным доступом к базовому значению. Он не предоставляет неизменяемый или общий доступ к базовому значению. MappedMutexGuard- Experimental RAII-страж мьютекса, возвращаемый MutexGuard::map, который может указывать на подполе защищенных данных. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята.MappedRwLockReadGuard- Experimental RAII-структура, используемая для освобождения общего доступа на чтение блокировки при удалении, которая может указывать на подполе защищенных данных.MappedRwLockWriteGuard- Experimental RAII-структура, используемая для освобождения эксклюзивного доступа на запись блокировки при удалении, которая может указывать на подполе защищенных данных.- [
ReentrantLock] - Experimental Реентерабельная (повторно входимая) блокировка взаимного исключения. - [
ReentrantLockGuard] - Experimental RAII-реализация «scoped lock» (блокировки с ограниченной областью видимости) реентерабельной блокировки. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята. - [
UniqueArc] - Experimental Уникально владеющий Arc.
Перечисления
TryLockError- Перечисление возможных ошибок, связанных с TryLockResult, которые могут возникнуть при попытке захвата блокировки, из метода try_lock на Mutex или методов try_read и try_write на RwLock.
Константы
- [
ONCE_INIT] - Deprecated Инициализирующее значение для статических значений Once.
Псевдонимы типов
-
[
LockResult] - Псевдоним типа для результата метода блокировки, который может быть отравлен. -
[
TryLockResult] - Псевдоним типа для результата неблокирующего метода блокировки.
Структуры
Arc- Потокобезопасный указатель с подсчётом ссылок. «Arc» означает «Atomically Reference Counted» (Атомарно Подсчитываемая Ссылка).Barrier- Барьер позволяет нескольким потокам синхронизировать начало некоторого вычисления.BarrierWaitResult- BarrierWaitResult возвращается методом Barrier::wait(), когда все потоки в Barrier встретились.Condvar- Условная переменная.LazyLock- Значение, которое инициализируется при первом доступе.Mutex- Примитив взаимного исключения, полезный для защиты общих данных.MutexGuard- RAII-реализация «scoped lock» (блокировки с ограниченной областью видимости) мьютекса. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята.Once- Низкоуровневый примитив синхронизации для однократного глобального выполнения.OnceLock- Примитив синхронизации, который номинально может быть записан только один раз.OnceState- Состояние, передаваемое в параметр замыкания Once::call_once_force(). Состояние может использоваться для запроса статуса отравления Once.PoisonError- Тип ошибки, который может возвращаться при захвате блокировки.RwLock- Читательско-писательская блокировка.RwLockReadGuard- RAII-структура, используемая для освобождения общего доступа на чтение блокировки при удалении.RwLockWriteGuard- RAII-структура, используемая для освобождения эксклюзивного доступа на запись блокировки при удалении.WaitTimeoutResult- Тип, указывающий, вернулась ли timed wait (ожидание с таймаутом) на условной переменной из-за таймаута или нет.Weak- Weak - это версия Arc, которая содержит невладеющую ссылку на управляемое выделение памяти.- [
Exclusive] - Experimental Exclusive предоставляет только изменяемый доступ, также называемый эксклюзивным доступом к базовому значению. Он не предоставляет неизменяемый или общий доступ к базовому значению. MappedMutexGuard- Experimental RAII-страж мьютекса, возвращаемый MutexGuard::map, который может указывать на подполе защищенных данных. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята.MappedRwLockReadGuard- Experimental RAII-структура, используемая для освобождения общего доступа на чтение блокировки при удалении, которая может указывать на подполе защищенных данных.MappedRwLockWriteGuard- Experimental RAII-структура, используемая для освобождения эксклюзивного доступа на запись блокировки при удалении, которая может указывать на подполе защищенных данных.- [
ReentrantLock] - Experimental Реентерабельная (повторно входимая) блокировка взаимного исключения. - [
ReentrantLockGuard] - Experimental RAII-реализация «scoped lock» (блокировки с ограниченной областью видимости) реентерабельной блокировки. Когда эта структура удаляется (выходит из области видимости), блокировка будет снята. - [
UniqueArc] - Experimental Уникально владеющий Arc.
Структура Arc
#![allow(unused)] fn main() { pub struct Arc<T, A = Global> where A: Allocator, T: ?Sized, { /* приватные поля */ } }
Потокобезопасный (Send + Sync) счетчик ссылок с атомарными операциями.
Тип Arc<T> предоставляет совместное владение значением типа T, выделенным в куче. Вызов clone на Arc создает новый экземпляр Arc, который указывает на то же самое выделение в куче, увеличивая при этом счетчик ссылок. Когда последний указатель Arc на выделение выходит из области видимости, значение удаляется (деструктор запускается), и память освобождается.
Совместное владение в Rust по умолчанию осуществляется через проверку заимствований. Rc<T> и Arc<T> позволяют обойти это ограничение: Rc использует проверки во время выполнения для обеспечения целостности, Arc использует атомарные операции.
Совместное владение также означает неизменность: невозможно получить изменяемую ссылку (&mut T) на значение внутри Arc, если только не используется другой механизм для обеспечения мутабельности, например Mutex или RwLock.
Умные указатели
Значения типа Arc<T> являются умными указателями: они указывают на значение типа T, расположенное в куче, и имеют метаданные счетчика ссылок. При создании Arc с помощью Arc::new метаданные счетчика ссылок также сохраняются в куче рядом с T. При клонировании Arc создается новый умный указатель, который указывает на то же самое размещение в куче.
Когда Arc выходит из области видимости, его реализация Drop уменьшает счетчик ссылок. Если счетчик ссылок достигает нуля, значение внутри T удаляется, а память освобождается.
Примеры
Потокобезопастельное совместное использование изменяемых данных:
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; let five = Arc::new(Mutex::new(5)); for _ in 0..10 { let five = Arc::clone(&five); thread::spawn(move || { let mut value = five.lock().unwrap(); *value += 1; }); } }
Clone
Создание ссылки на тот же самый allocation:
#![allow(unused)] fn main() { use std::sync::Arc; let foo = Arc::new(vec![1.0, 2.0, 3.0]); // Две ссылки на одни и те же данные let a = foo.clone(); let b = Arc::clone(&foo); // a, b и foo - все Arc, указывающие на одни и те же данные }
Функция Arc::clone(&from) семантически эквивалентна from.clone(), но более идиоматична.
Deref поведение
Arc<T> автоматически разыменовывается в T (благодаря реализации Deref), поэтому вы можете вызывать методы T непосредственно на Arc<T>. Чтобы избежать конфликта имен с методами T, методы Arc<T>которые являются ассоциированными функциями (вызываются как Arc::get_mut(&mut value) вместо value.get_mut()).
#![allow(unused)] fn main() { use std::sync::Arc; let my_arc = Arc::new(()); let my_arc_clone = Arc::clone(&my_arc); }
Также следует учитывать автоматическое разыменование при сравнении:
#![allow(unused)] fn main() { use std::sync::Arc; let five = Arc::new(5); assert!(five == 5); // Автоматическое разыменование в i32 }
Примеры совместного использования между потоками
#![allow(unused)] fn main() { use std::sync::Arc; use std::thread; let five = Arc::new(5); for _ in 0..10 { let five = Arc::clone(&five); thread::spawn(move || { println!("{five:?}"); }); } }
Примеры Weak
Слабые ссылки (Weak) не предотвращают удаление allocation:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; let strong = Arc::new("hello".to_owned()); let weak = Arc::downgrade(&strong); // Сильная ссылка все еще существует, значение доступно assert_eq!(1, Arc::weak_count(&strong)); assert_eq!(Some("hello"), weak.upgrade().as_deref()); drop(strong); // Теперь значение удалено assert!(weak.upgrade().is_none()); }
Отличия от std::rc::Rc
Arc использует атомарные операции для подсчета ссылок, что означает его безопасность для совместного использования между потоками. Однако это влечет накладные расходы по производительности, которых нет у Rc. Rc не является потокобезопасным и не реализует Send или Sync.
Атомарность
Arc использует глобально атомарные операции для подсчета ссылок. На современных процессорах это часто достигается с помощью инструкций с блокировкой кэша. Однако системы без атомарных операций могут использовать спин-блокировки или другие механизмы.
Безопасность для циклических ссылок
Arc по умолчанию не предотвращает циклические ссылки. Это может привести к утечкам памяти. Для предотвращения циклических ссылок используйте Weak.
Трейт-объекты
Когда T имеет типаж Dyn (например, dyn SomeTrait), Arc автоматически реализует соответствующие типажи, такие как DynSomeTrait.
Реализации
Arc<str>:Arc<str>не имеет нуль-терминатора и может использоваться для строковых срезовArc<[T]>:Arc<[T]>может использоваться для срезов массиваArc<CStr>:Arc<CStr>может использоваться для строк в стиле C
Методы
Создание
new(value: T) -> Arc<T>- Создает новыйArc<T>new_cyclic(data_fn: F) -> Arc<T>- СоздаетArcс циклической ссылкойnew_uninit() -> Arc<MaybeUninit<T>>- Создает неинициализированныйArcpin(value: T) -> Pin<Arc<T>>- Закрепляет значение в памяти
Получение внутренних данных
into_raw(this: Arc<T>) -> *const T- Преобразует в сырой указательfrom_raw(ptr: *const T) -> Arc<T>- Восстанавливает из сырого указателяas_ptr(this: &Arc<T>) -> *const T- Получает сырой указатель
Счетчики ссылок
strong_count(this: &Arc<T>) -> usize- Количество сильных ссылокweak_count(this: &Arc<T>) -> usize- Количество слабых ссылок
Слабые ссылки
downgrade(this: &Arc<T>) -> Weak<T>- Создает слабую ссылкуtry_unwrap(this: Arc<T>) -> Result<T, Arc<T>>- Извлекает значение, если это последняя сильная ссылка
Сравнения
ptr_eq(this: &Arc<T>, other: &Arc<T>) -> bool- Проверяет, указывают ли на одно allocation
Реализации трейтов
Clone,Debug,Default,Deref,DropFrom<T>,From<Box<T>>,From<String>,From<&str>PartialEq,Eq,PartialOrd,Ord,HashSend,Sync(когдаT: Send + Sync)Pointer,Display
Автоматические реализации трейтов
!Unpin(когдаT: ?Unpin)UnwindSafe(когдаT: UnwindSafe)RefUnwindSafe(когдаT: RefUnwindSafe)
Структура Barrier
#![allow(unused)] fn main() { pub struct Barrier { /* приватные поля */ } }
Барьер обеспечивает точку синхронизации, в которой несколько потоков будут ждать, пока все они не достигнут этой точки.
Барьеры используются для обеспечения того, что несколько потоков выполняют определенные участки кода одновременно.
Примеры
#![allow(unused)] fn main() { use std::sync::{Arc, Barrier}; use std::thread; let mut handles = Vec::with_capacity(10); let barrier = Arc::new(Barrier::new(10)); for _ in 0..10 { let c = Arc::clone(&barrier); // То же самое, что и clone: let c = barrier.clone(); handles.push(thread::spawn(move|| { println!("до ожидания"); c.wait(); println!("после ожидания"); })); } // Ждем завершения всех потоков for handle in handles { handle.join().unwrap(); } }
Методы
new
#![allow(unused)] fn main() { pub fn new(n: usize) -> Barrier }
Создает новый барьер, который может блокировать заданное количество потоков.
Барьер будет блокировать вызовы wait(), пока n потоков не будут ожидать на нем. Затем все потоки будут разблокированы одновременно.
Примеры
#![allow(unused)] fn main() { use std::sync::Barrier; let barrier = Barrier::new(10); }
wait
#![allow(unused)] fn main() { pub fn wait(&self) -> BarrierWaitResult }
Блокирует текущий поток до тех пор, пока все потоки не встретятся здесь.
Барьер выполняется циклически: после того как все потоки собрались вместе, они могут продолжать работу, и барьер может быть использован снова.
Возвращает BarrierWaitResult, указывающий, был ли этот поток "лидером" при прорыве барьера.
Только один поток получит BarrierWaitResult, у которого is_leader() возвращает true, когда барьер прорывается, и все остальные потоки получат результат, у которого is_leader() возвращает false.
Примеры
#![allow(unused)] fn main() { use std::sync::{Arc, Barrier}; use std::thread; let mut handles = Vec::with_capacity(10); let barrier = Arc::new(Barrier::new(10)); let leader = Arc::new(std::sync::Mutex::new(None)); for i in 0..10 { let c = Arc::clone(&barrier); let leader_ref = Arc::clone(&leader); handles.push(thread::spawn(move|| { let wait_result = c.wait(); if wait_result.is_leader() { *leader_ref.lock().unwrap() = Some(i); } })); } // Ждем завершения всех потоков for handle in handles { handle.join().unwrap(); } // Проверяем, какой поток был лидером let leader_id = leader.lock().unwrap().unwrap(); println!("Поток {} был лидером", leader_id); }
Поведение
Постоянство
Барьеры можно использовать многократно и будут продолжать работать постоянно.
Потокобезопасность
Барьеры являются Sync и могут использоваться совместно между несколькими потоками.
Производительность
Реализация барьера использует мьютекс и условную переменную, что может быть не самым эффективным решением для высокопроизводительных сценариев. Для таких случаев могут существовать специализированные крейты.
Пример практического использования
Синхронизация начала вычислений:
#![allow(unused)] fn main() { use std::sync::{Arc, Barrier}; use std::thread; use std::time::Instant; let data = Arc::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); let barrier = Arc::new(Barrier::new(4)); let mut handles = vec![]; for i in 0..4 { let data = Arc::clone(&data); let barrier = Arc::clone(&barrier); handles.push(thread::spawn(move || { // Ждем, пока все потоки не будут готовы barrier.wait(); let start = Instant::now(); // Каждый поток обрабатывает свою часть данных let chunk_size = data.len() / 4; let start_idx = i * chunk_size; let end_idx = if i == 3 { data.len() } else { start_idx + chunk_size }; let sum: i32 = data[start_idx..end_idx].iter().sum(); (sum, start.elapsed()) })); } let mut total_sum = 0; for handle in handles { let (sum, duration) = handle.join().unwrap(); total_sum += sum; println!("Поток вычислил сумму {} за {:?}", sum, duration); } println!("Общая сумма: {}", total_sum); }
Совместимость
Барьеры доступны с Rust 1.0.0 и являются стандартным способом синхронизации потоков по точкам встречи.
Структура BarrierWaitResult
#![allow(unused)] fn main() { pub struct BarrierWaitResult(/* приватные поля */); }
Возвращается Barrier::wait, когда все потоки в барьере встретились.
Пример
#![allow(unused)] fn main() { use std::sync::{Barrier, Arc}; use std::thread; let mut handles = Vec::with_capacity(10); let barrier = Arc::new(Barrier::new(10)); for _ in 0..10 { let c = Arc::clone(&barrier); // Те же сообщения будут打印出来 вместе. // Мы увидим это из порядков вывода. handles.push(thread::spawn(move|| { println!("before wait"); let wait_result = c.wait(); println!("after wait"); wait_result })); } // Ждем завершения других потоков. let mut num_leaders = 0; for handle in handles { let wait_result = handle.join().unwrap(); if wait_result.is_leader() { num_leaders += 1; } } // Только один поток становится лидером. assert_eq!(num_leaders, 1); }
Методы
pub fn is_leader(&self) -> bool
Возвращает true, если этот поток является "лидером" вызова wait.
Только один поток из группы, ожидающей на барьере, будет выбран в качестве "лидера". Этот поток получит BarrierWaitResult, который возвращает true от is_leader, когда вызов wait возвращается.
Пример
#![allow(unused)] fn main() { use std::sync::Barrier; let barrier = Barrier::new(1); let barrier_wait_result = barrier.wait(); assert!(barrier_wait_result.is_leader()); }
pub fn is_leader(&self) -> bool
Возвращает true, если этот поток является "лидером" вызова wait.
Только один поток из группы, ожидающей на барьере, будет выбран в качестве "лидера". Этот поток получит BarrierWaitResult, который возвращает true от is_leader, когда вызов wait возвращается.
Пример
#![allow(unused)] fn main() { use std::sync::Barrier; let barrier = Barrier::new(1); let barrier_wait_result = barrier.wait(); assert!(barrier_wait_result.is_leader()); }
Реализации Trait
impl Debug for BarrierWaitResult
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Форматирует значение с помощью заданного форматировщика.
impl PartialEq<BarrierWaitResult> for BarrierWaitResult
fn eq(&self, other: &BarrierWaitResult) -> bool
Этот метод проверяет равенство значений self и other, и используется оператором ==.
fn ne(&self, other: &BarrierWaitResult) -> bool
Этот метод проверяет неравенство !=. Реализация по умолчанию почти всегда достаточна, и её не следует переопределять без веской причины.
impl Eq for BarrierWaitResult
Auto Trait Implementation
impl RefUnwindSafe for BarrierWaitResult
impl Send for BarrierWaitResult
impl Sync for BarrierWaitResult
impl Unpin for BarrierWaitResult
impl UnwindSafe for BarrierWaitResult
Автоматические реализации Trait
impl<T> Any for T where T: 'static + ?Sized,
impl<T> Borrow<T> for T where T: ?Sized,
impl<T> BorrowMut<T> for T where T: ?Sized,
impl<T> From<T> for T
impl<T, U> Into<U> for T where U: From<T>,
impl<T> ToOwned for T where T: Clone,
impl<T, U> TryFrom<U> for T where U: Into<T>,
impl<T, U> TryInto<U> for T where U: TryFrom<T>,
Структура Condvar
#![allow(unused)] fn main() { pub struct Condvar { /* приватные поля */ } }
Условная переменная.
Условные переменные представляют собой возможность блокировать поток до тех пор, пока не будет выполнено определенное условие.
Условные переменные обычно используются в паре с мьютексом. Как правило, условная переменная используется для защиты данных, а мьютекс используется для обеспечения эксклюзивного доступа к данным, в то время как условная переменная используется для сигнализации об изменении данных.
Этот модуль поддерживает два типа условных переменных:
Condvar- стандартная реализация условной переменной, которая может быть создана с помощьюCondvar::new().StaticCondvar- статическая инициализация условной переменной.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); // Внутренний поток, который будет устанавливать условие thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; // Уведомляем один ожидающий поток cvar.notify_one(); }); // Ждем, пока условие не станет true let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); while !*started { started = cvar.wait(started).unwrap(); } }
Методы
pub fn new() -> Condvar
Создает новую условную переменную.
Пример
#![allow(unused)] fn main() { use std::sync::Condvar; let condvar = Condvar::new(); }
pub fn wait<'a, T>( &self, guard: MutexGuard<'a, T> ) -> LockResult<MutexGuard<'a, T>>
Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление.
Эта функция атомарно разблокирует указанный мьютекс и блокирует текущий поток. Когда поток блокируется, вызывающий поток должен обеспечить, чтобы охрана мьютекса была временно освобождена, чтобы позволить другим потокам получить доступ к данным, защищенным мьютексом.
Когда эта функция возвращается, указанная охрана мьютекса будет повторно получена.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); while !*started { started = cvar.wait(started).unwrap(); } }
pub fn wait_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, condition: F ) -> LockResult<MutexGuard<'a, T>> where F: FnMut(&mut T) -> bool,
Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление и указанное условие не станет ложным.
Эта функция атомарно разблокирует указанный мьютекс и блокирует текущий поток. Когда поток блокируется, вызывающий поток должен обеспечить, чтобы охрана мьютекса была временно освобождена, чтобы позволить другим потокам получить доступ к данным, защищенным мьютексом.
Когда эта функция возвращается, указанная охрана мьютекса будет повторно получена.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::new((Mutex::new(true), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut pending = lock.lock().unwrap(); *pending = false; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut pending = lock.lock().unwrap(); while *pending { pending = cvar.wait_while(pending, |pending| *pending).unwrap(); } }
pub fn wait_timeout<'a, T>( &self, guard: MutexGuard<'a, T>, timeout: Duration ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление или не истечет указанное время ожидания.
Возвращаемое значение указывает, сколько времени осталось до истечения таймаута.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; use std::time::Duration; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); loop { let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap(); started = result.0; if *started { break; } if result.1.timed_out() { // Таймаут истек без получения уведомления break; } } }
pub fn wait_timeout_while<'a, T, F>( &self, guard: MutexGuard<'a, T>, timeout: Duration, condition: F ) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> where F: FnMut(&mut T) -> bool,
Блокирует текущий поток до тех пор, пока эта условная переменная не получит уведомление, указанное условие не станет ложным или не истечет указанное время ожидания.
Возвращаемое значение указывает, осталось ли время до истечения таймаута.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; use std::time::Duration; let pair = Arc::new((Mutex::new(true), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut pending = lock.lock().unwrap(); *pending = false; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut pending = lock.lock().unwrap(); loop { let result = cvar.wait_timeout_while( pending, Duration::from_millis(100), |&mut pending| pending ).unwrap(); pending = result.0; if !*pending { break; } if result.1.timed_out() { // Таймаут истек, но условие все еще истинно break; } } }
pub fn notify_one(&self)
Пробуждает один поток, ожидающий на этой условной переменной.
Если есть потоки, заблокированные на этой условной переменной, то этот вызов пробудит один из них.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move|| { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); while !*started { started = cvar.wait(started).unwrap(); } }
pub fn notify_all(&self)
Пробуждает все потоки, ожидающие на этой условной переменной.
Этот метод гарантирует, что все потоки, заблокированные на этой условной переменной, будут пробуждены.
Пример
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); for _ in 0..3 { let pair3 = Arc::clone(&pair2); thread::spawn(move|| { let (lock, cvar) = &*pair3; let mut started = lock.lock().unwrap(); while !*started { started = cvar.wait(started).unwrap(); } }); } let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); *started = true; cvar.notify_all(); }
Trait реализации
impl Debug for Condvar
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Форматирует значение с использованием заданного форматировщика.
impl Default for Condvar
fn default() -> Condvar
Возвращает "значение по умолчанию" для типа.
Автоматические реализации Trait
impl RefUnwindSafe for Condvar
impl Send for Condvar
impl Sync for Condvar
impl UnwindSafe for Condvar
Blanket реализации
impl<T> Any for T where T: 'static + ?Sized,
impl<T> Borrow<T> for T where T: ?Sized,
impl<T> BorrowMut<T> for T where T: ?Sized,
impl<T> From<T> for T
impl<T, U> Into<U> for T where U: From<T>,
impl<T> ToOwned for T where T: Clone,
impl<T, U> TryFrom<U> for T where U: Into<T>,
impl<T, U> TryInto<U> for T where U: TryFrom<T>,
Структура LazyLock
#![allow(unused)] fn main() { pub struct LazyLock<T, F = fn() -> T> { /* приватные поля */ } }
Значение, которое инициализируется при первом доступе.
Для совместного использования между потоками, LazyLock должен быть обернут в примитив синхронизации, такой как Arc.
Пример
use std::sync::LazyLock; static LAZY: LazyLock<String> = LazyLock::new(|| { "Hello, World!".to_string() }); fn main() { println!("{}", *LAZY); // Печатает "Hello, World!" }
Методы
pub const fn new(f: F) -> LazyLock<T, F>
Создает новый экземпляр LazyLock с заданной функцией инициализации.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| 92); // Доступ к значению инициализирует его assert_eq!(*lazy, 92); }
pub fn into_inner(this: LazyLock<T, F>) -> Result<T, F>
Потребляет этот LazyLock, возвращая сохраненное значение.
Возвращает Ok(value), если LazyLock уже инициализирован, и Err(f), если он еще не инициализирован.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| 92); assert_eq!(LazyLock::into_inner(lazy).unwrap(), 92); }
pub fn force(this: &LazyLock<T, F>) -> &T where F: FnOnce() -> T,
Принудительно вычисляет и возвращает ссылку на значение.
Это эквивалентно разыменованию, но более явное.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| 92); // Принудительная инициализация assert_eq!(LazyLock::force(&lazy), &92); // Или просто разыменование assert_eq!(*lazy, 92); }
pub fn get(this: &LazyLock<T, F>) -> Option<&T>
Получает ссылку на результат вычисления, если он уже инициализирован.
Возвращает Some, если LazyLock уже инициализирован, и None в противном случае.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| 92); // Еще не инициализирован assert_eq!(LazyLock::get(&lazy), None); // После доступа инициализируется let _ = *lazy; assert_eq!(LazyLock::get(&lazy), Some(&92)); }
Реализации Trait
impl<T, F> Deref for LazyLock<T, F> where F: FnOnce() -> T,
type Target = T
Результирующий тип после разыменования.
fn deref(&self) -> &T
Разыменовывает значение.
При первом вызове этого метода будет вызвана функция инициализации для вычисления значения. Последующие вызовы вернут кэшированное значение.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| { println!("Инициализация значения"); 42 }); // При первом доступе печатает "Инициализация значения" println!("{}", *lazy); // 42 // При последующих доступах значение берется из кэша println!("{}", *lazy); // 42 }
impl<T, F> DerefMut for LazyLock<T, F> where F: FnOnce() -> T,
fn deref_mut(&mut self) -> &mut T
Разыменовывает значение с возможностью изменения.
При первом вызове этого метода будет вызвана функция инициализации для вычисления значения. Последующие вызовы вернут кэшированное значение.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let mut lazy = LazyLock::new(|| vec![1, 2, 3]); // Инициализирует и получает изменяемую ссылку lazy.push(4); assert_eq!(*lazy, vec![1, 2, 3, 4]); }
impl<T, F> Debug for LazyLock<T, F> where T: Debug,
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Форматирует значение с использованием заданного форматировщика.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::new(|| 42); println!("{:?}", lazy); // Печатает отладочное представление }
impl<T, F> Default for LazyLock<T, F> where F: Default,
fn default() -> LazyLock<T, F>
Возвращает "значение по умолчанию" для типа.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; #[derive(Default)] struct MyInit; let lazy: LazyLock<i32, _> = LazyLock::default(); }
impl<T, F: FnOnce() -> T> From<F> for LazyLock<T, F>
fn from(f: F) -> LazyLock<T, F>
Создает новый LazyLock из функции инициализации.
Пример
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy = LazyLock::from(|| "hello".to_string()); assert_eq!(*lazy, "hello"); }
Автоматические реализации Trait
impl<T, F> RefUnwindSafe for LazyLock<T, F> where F: RefUnwindSafe, T: RefUnwindSafe,
impl<T, F> Send for LazyLock<T, F> where F: Send, T: Send,
impl<T, F> Sync for LazyLock<T, F> where F: Sync, T: Sync,
impl<T, F> Unpin for LazyLock<T, F> where F: Unpin, T: Unpin,
impl<T, F> UnwindSafe for LazyLock<T, F> where F: UnwindSafe, T: UnwindSafe,
Blanket реализации
impl<T> Any for T where T: 'static + ?Sized,
impl<T> Borrow<T> for T where T: ?Sized,
impl<T> BorrowMut<T> for T where T: ?Sized,
impl<T> From<T> for T
impl<T, U> Into<U> for T where U: From<T>,
impl<T> ToOwned for T where T: Clone,
impl<T, U> TryFrom<U> for T where U: Into<T>,
impl<T, U> TryInto<U> for T where U: TryFrom<T>,
Примеры использования
Статическая ленивая инициализация
use std::sync::LazyLock; use std::collections::HashMap; static HASHMAP: LazyLock<HashMap<i32, String>> = LazyLock::new(|| { println!("Инициализация HashMap"); let mut m = HashMap::new(); m.insert(13, "Spica".to_string()); m.insert(74, "Hoyten".to_string()); m }); fn main() { println!("Готов"); println!("{:?}", *HASHMAP); }
Ленивая инициализация с захватом переменных
use std::sync::LazyLock; fn create_lazy() -> LazyLock<Vec<i32>> { let base_value = 10; LazyLock::new(|| { vec![base_value, base_value * 2, base_value * 3] }) } fn main() { let lazy_vec = create_lazy(); assert_eq!(*lazy_vec, vec![10, 20, 30]); }
Использование с изменяемым доступом
#![allow(unused)] fn main() { use std::sync::LazyLock; let mut lazy_counter = LazyLock::new(|| 0); // Увеличиваем счетчик после инициализации *lazy_counter += 1; assert_eq!(*lazy_counter, 1); }
Проверка состояния инициализации
#![allow(unused)] fn main() { use std::sync::LazyLock; let lazy_value = LazyLock::new(|| 42); // Проверяем, инициализирован ли уже assert!(LazyLock::get(&lazy_value).is_none()); // Инициализируем доступом let _ = *lazy_value; // Теперь инициализирован assert!(LazyLock::get(&lazy_value).is_some()); }
MappedMutexGuard
MappedRwLockReadGuard
MappedRwLockWriteGuard
Структура Mutex
#![allow(unused)] fn main() { pub struct Mutex<T: ?Sized> { /* приватные поля */ } }
Примитив взаимного исключения, полезный для защиты общих данных.
Этот мьютекс может блокировать поддержку ожидания вызовов. У каждого мьютекса есть тип, представляющий данные, которые он защищает. Для доступа к этим данным необходимо получить охрану мьютекса через вызов lock или try_lock, который возвращает [MutexGuard]. Охрана поддерживает доступ к данным через типаж Deref и позволяет изменять данные через типаж DerefMut.
Отравление
Мьютексы в этом модуле реализуют стратегию под названием "отравление", при которой мьютекс становится отравленным, если он обнаруживает, что поток, удерживающий его, запаниковал.
Как только мьютекс отравлен, все другие потоки по умолчанию не могут получить доступ к данным, так как они, вероятно, испорчены (некоторый инвариант не соблюдается). Для мьютекса это означает, что методы lock и try_lock возвращают Result, который указывает, был ли мьютекс отравлен или нет. В большинстве случаев использования мьютекса эти результаты просто unwrap(), распространяя паники между потоками, чтобы гарантировать, что возможно недействительный инвариант не будет замечен.
Отравление является только рекомендательным: тип PoisonError имеет метод into_inner, который вернет охрану, которая была бы возвращена при успешной блокировке. Это позволяет получить доступ к данным, несмотря на то, что блокировка отравлена.
Кроме того, обнаружение паники не является идеальным, поэтому даже неотравленные мьютексы нужно обрабатывать с осторожностью, поскольку определенные паники могли быть пропущены. Вот неисчерпывающий список ситуаций, когда это может произойти:
- Если мьютекс блокируется во время паники, например, в реализации
Dropили обработчике паники, паника во второй раз при удержании блокировки оставит мьютекс неотравленным. Заметьте, что хотя двойная паника обычно завершает программу,catch_unwindможет предотвратить это. - Блокировка и разблокировка мьютекса в разных контекстах паники, например, путем сохранения охраны в
CellвнутриDrop::dropи доступа к ней снаружи, или наоборот, может повлиять на статус отравления неожиданным образом. - Иностранные исключения в настоящее время не вызывают отравление даже при отсутствии других паник.
Хотя это редко происходит в реальном коде, небезопасный код не может полагаться на отравление для корректности, поскольку поведение отравления может зависеть от внешнего контекста. Вот пример неправильного использования отравления:
#![allow(unused)] fn main() { use std::sync::Mutex; struct MutexBox<T> { data: Mutex<*mut T>, } impl<T> MutexBox<T> { pub fn new(value: T) -> Self { Self { data: Mutex::new(Box::into_raw(Box::new(value))), } } pub fn replace_with(&self, f: impl FnOnce(T) -> T) { let ptr = self.data.lock().expect("poisoned"); // Пока выполняется `f`, данные перемещаются из `*ptr`. Если `f` // запаникует, `*ptr` продолжит указывать на удаленное значение. Намерение // состоит в том, что это отравит мьютекс, поэтому следующие вызовы // `replace_with` запаникуют без чтения `*ptr`. Но поскольку // отравление не гарантируется, если это выполняется из обработчика паники, // это может привести к использованию после освобождения. unsafe { (*ptr).write(f((*ptr).read())); } } } }
Примеры
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; use std::sync::mpsc::channel; const N: usize = 10; // Создаем несколько потоков для увеличения общей переменной (неатомарно), и // сообщаем основному потоку, когда все увеличения завершены. // // Здесь мы используем Arc для совместного использования памяти между потоками, и данные внутри // Arc защищены мьютексом. let data = Arc::new(Mutex::new(0)); let (tx, rx) = channel(); for _ in 0..N { let (data, tx) = (Arc::clone(&data), tx.clone()); thread::spawn(move || { // К общему состоянию можно получить доступ только после получения блокировки. // Наше неатомарное увеличение безопасно, потому что мы единственный поток, // который может получить доступ к общему состоянию, когда блокировка удерживается. // // Мы используем unwrap() для возвращаемого значения, чтобы утверждать, что мы не ожидаем, // что потоки когда-либо завершатся неудачей при удержании блокировки. let mut data = data.lock().unwrap(); *data += 1; if *data == N { tx.send(()).unwrap(); } // блокировка разблокируется здесь, когда `data` выходит из области видимости. }); } rx.recv().unwrap(); }
Чтобы восстановиться после отравленного мьютекса:
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; let lock = Arc::new(Mutex::new(0_u32)); let lock2 = Arc::clone(&lock); let _ = thread::spawn(move || -> () { // Этот поток получит мьютекс первым, разворачивая результат // `lock`, потому что блокировка не была отравлена. let _guard = lock2.lock().unwrap(); // Эта паника при удержании блокировки (`_guard` в области видимости) отравит // мьютекс. panic!(); }).join(); // Блокировка отравлена к этому моменту, но возвращаемый результат может быть // сопоставлен с образцом, чтобы вернуть базовую охрану в обеих ветвях. let mut guard = match lock.lock() { Ok(guard) => guard, Err(poisoned) => poisoned.into_inner(), }; *guard += 1; }
Чтобы разблокировать охрану мьютекса раньше, чем конец охватывающей области видимости, либо создайте внутреннюю область видимости, либо вручную удалите охрану.
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; const N: usize = 3; let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); let res_mutex = Arc::new(Mutex::new(0)); let mut threads = Vec::with_capacity(N); (0..N).for_each(|_| { let data_mutex_clone = Arc::clone(&data_mutex); let res_mutex_clone = Arc::clone(&res_mutex); threads.push(thread::spawn(move || { // Здесь мы используем блок для ограничения времени жизни охраны блокировки. let result = { let mut data = data_mutex_clone.lock().unwrap(); // Это результат некоторой важной и длительной работы. let result = data.iter().fold(0, |acc, x| acc + x * 2); data.push(result); result // Охрана мьютекса удаляется здесь вместе с любыми другими значениями, // созданными в критической секции. }; // Охрана, созданная здесь, является временной и удаляется в конце оператора, т.е. // блокировка не останется удержанной, даже если поток выполнит дополнительную работу. *res_mutex_clone.lock().unwrap() += result; })); }); let mut data = data_mutex.lock().unwrap(); // Это результат некоторой важной и длительной работы. let result = data.iter().fold(0, |acc, x| acc + x * 2); data.push(result); // Мы явно удаляем `data`, потому что это больше не нужно и // поток все еще имеет работу для выполнения. Это позволяет другим потокам начать работу с // данными немедленно, не дожидаясь завершения остальной несвязанной работы // здесь. // // Это еще более важно здесь, чем в потоках, потому что мы `.join` // потоки после этого. Если бы мы не удалили охрану мьютекса, поток мог бы // ждать ее вечно, вызывая взаимную блокировку. // Как и в потоках, вместо вызова функции `drop` можно было использовать блок. drop(data); // Здесь охрана мьютекса не присваивается переменной, и поэтому, даже если // область видимости не заканчивается после этой строки, мьютекс все равно освобождается: нет // взаимной блокировки. *res_mutex.lock().unwrap() += result; threads.into_iter().for_each(|thread| { thread .join() .expect("The thread creating or execution failed !") }); assert_eq!(*res_mutex.lock().unwrap(), 800); }
Реализации
impl<T> Mutex<T>
pub const fn new(t: T) -> Mutex<T>
Создает новый мьютекс в разблокированном состоянии, готовый к использованию.
pub fn get_cloned(&self) -> Result<T, PoisonError<()>> where T: Clone,
🔬 Это экспериментальное API, доступное только в ночных сборках.
Возвращает содержащееся значение путем его клонирования.
Ошибки: Если другой пользователь этого мьютекса запаниковал, удерживая мьютекс, то этот вызов вернет ошибку.
pub fn set(&self, value: T) -> Result<(), PoisonError<T>>
🔬 Это экспериментальное API, доступное только в ночных сборках.
Устанавливает содержащееся значение.
Ошибки: Если другой пользователь этого мьютекса запаниковал, удерживая мьютекс, то этот вызов вернет ошибку, содержащую предоставленное значение.
pub fn replace(&self, value: T) -> LockResult<T>
🔬 Это экспериментальное API, доступное только в ночных сборках.
Заменяет содержащееся значение на value и возвращает старое содержащееся значение.
Ошибки: Если другой пользователь этого мьютекса запаниковал, удерживая мьютекс, то этот вызов вернет ошибку, содержащую предоставленное значение.
impl<T: ?Sized> Mutex<T>
pub fn lock(&self) -> LockResult<MutexGuard<'_, T>>
Получает мьютекс, блокируя текущий поток до тех пор, пока он не сможет это сделать.
pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>>
Пытается получить эту блокировку.
pub fn is_poisoned(&self) -> bool
Определяет, отравлен ли мьютекс в данный момент.
pub fn clear_poison(&self)
Очищает состояние отравления мьютекса.
pub fn into_inner(self) -> LockResult<T> where T: Sized,
Потребляет этот мьютекс, возвращая базовые данные.
pub fn get_mut(&mut self) -> LockResult<&mut T>
Возвращает изменяемую ссылку на базовые данные.
pub fn data_ptr(&self) -> *mut T
🔬 Это экспериментальное API, доступное только в ночных сборках.
Возвращает сырой указатель на базовые данные.
Структура MutexGuard
#![allow(unused)] fn main() { pub struct MutexGuard<'a, T: ?Sized + 'a> { /* приватные поля */ } }
Описание
RAII-реализация «блокировки с областью видимости» мьютекса. Когда эта структура удаляется (выходит из области видимости), блокировка будет автоматически снята.
Данные, защищенные мьютексом, могут быть доступны через эту защиту с помощью реализаций Deref и DerefMut.
Эта структура создается методами lock и try_lock у Mutex.
Методы
map
#![allow(unused)] fn main() { pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'a, U> where F: FnOnce(&mut T) -> &mut U, U: ?Sized, }
🔬 Это экспериментальное API только для ночных сборок. (mapped_lock_guards #117108)
Создает MappedMutexGuard для компонента заимствованных данных, например, варианта перечисления.
Мьютекс уже заблокирован, поэтому этот метод не может завершиться неудачей.
Это ассоциированная функция, которая должна использоваться как MutexGuard::map(...). Метод бы конфликтовал с методами с тем же именем у содержимого MutexGuard, используемого через Deref.
filter_map
#![allow(unused)] fn main() { pub fn filter_map<U, F>( orig: Self, f: F, ) -> Result<MappedMutexGuard<'a, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>, U: ?Sized, }
🔬 Это экспериментальное API только для ночных сборок. (mapped_lock_guards #117108)
Создает MappedMutexGuard для компонента заимствованных данных. Оригинальная защита возвращается как Err(...), если замыкание возвращает None.
Мьютекс уже заблокирован, поэтому этот метод не может завершиться неудачей.
Это ассоциированная функция, которая должна использоваться как MutexGuard::filter_map(...). Метод бы конфликтовал с методами с тем же именем у содержимого MutexGuard, используемого через Deref.
Реализации трейтов
Debug
1.16.0
#![allow(unused)] fn main() { impl<T: ?Sized + Debug> Debug for MutexGuard<'_, T> }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result }
Форматирует значение с помощью заданного форматировщика.
Deref
1.0.0
#![allow(unused)] fn main() { impl<T: ?Sized> Deref for MutexGuard<'_, T> }
Ассоциированный тип Target
#![allow(unused)] fn main() { type Target = T }
Тип результата после разыменования.
deref
#![allow(unused)] fn main() { fn deref(&self) -> &T }
Разыменовывает значение.
DerefMut
1.0.0
#![allow(unused)] fn main() { impl<T: ?Sized> DerefMut for MutexGuard<'_, T> }
deref_mut
#![allow(unused)] fn main() { fn deref_mut(&mut self) -> &mut T }
Мутабельно разыменовывает значение.
Display
1.20.0
#![allow(unused)] fn main() { impl<T: ?Sized + Display> Display for MutexGuard<'_, T> }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result }
Форматирует значение с помощью заданного форматировщика.
Drop
1.0.0
#![allow(unused)] fn main() { impl<T: ?Sized> Drop for MutexGuard<'_, T> }
drop
#![allow(unused)] fn main() { fn drop(&mut self) }
Выполняет деструктор для этого типа.
!Send
1.0.0
#![allow(unused)] fn main() { impl<T: ?Sized> !Send for MutexGuard<'_, T> }
MutexGuard не является Send для максимальной переносимости между платформами.
На платформах, использующих POSIX threads (обычно называемые pthreads), существует требование освобождать блокировки мьютексов в том же потоке, в котором они были получены. По этой причине MutexGuard не должен реализовывать Send, чтобы предотвратить его удаление из другого потока.
Sync
1.19.0
#![allow(unused)] fn main() { impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> }
T должен быть Sync для того, чтобы MutexGuard<T> был Sync, потому что возможно получить &T из &MutexGuard (через Deref).
Автоматические реализации трейтов
Freeze
#![allow(unused)] fn main() { impl<'a, T> Freeze for MutexGuard<'a, T> where T: ?Sized, }
RefUnwindSafe
#![allow(unused)] fn main() { impl<'a, T> RefUnwindSafe for MutexGuard<'a, T> where T: ?Sized, }
Unpin
#![allow(unused)] fn main() { impl<'a, T> Unpin for MutexGuard<'a, T> where T: ?Sized, }
UnwindSafe
#![allow(unused)] fn main() { impl<'a, T> UnwindSafe for MutexGuard<'a, T> where T: ?Sized, }
Стандартные реализации
(Реализации стандартных трейтов для всех типов остаются без изменений)
Структура Once
#![allow(unused)] fn main() { pub struct Once { /* приватные поля */ } }
Описание
Низкоуровневый примитив синхронизации для однократного глобального выполнения.
Ранее это была единственная синхронизация "выполнить один раз" в std. Другие библиотеки реализовывали новые синхронизирующие типы с помощью Once, такие как OnceLock<T> или LazyLock<T, F>, до того как они были добавлены в std. В частности, OnceLock<T> заменяет Once по функциональности и должен быть предпочтительнее для общего случая, когда Once ассоциирован с данными.
Этот тип может быть создан только с помощью Once::new().
Примеры
#![allow(unused)] fn main() { use std::sync::Once; static START: Once = Once::new(); START.call_once(|| { // выполнить инициализацию здесь }); }
Методы
new
#![allow(unused)] fn main() { pub const fn new() -> Once }
1.2.0 (const: 1.32.0)
Создает новое значение Once.
call_once
#![allow(unused)] fn main() { pub fn call_once<F>(&self, f: F) where F: FnOnce(), }
1.0.0
Выполняет процедуру инициализации один и только один раз. Данное замыкание будет выполнено, если это первый вызов call_once, в противном случае процедура не будет вызвана.
Этот метод заблокирует вызывающий поток, если другая процедура инициализации в настоящее время выполняется.
Когда эта функция возвращает управление, гарантируется, что некоторая инициализация была выполнена и завершена (это может быть не указанное замыкание). Также гарантируется, что любые записи в память, выполненные выполненным замыканием, могут быть надежно наблюдаемы другими потоками в этот момент (существует отношение happens-between между замыканием и кодом, выполняющимся после возврата).
Если данное замыкание рекурсивно вызывает call_once на том же экземпляре Once, точное поведение не указано: допустимыми исходами являются паника или взаимная блокировка.
Примеры
#![allow(unused)] fn main() { use std::sync::Once; static mut VAL: usize = 0; static INIT: Once = Once::new(); // Доступ к `static mut` небезопасен большую часть времени, но если мы делаем это // синхронизированным образом (например, запись один раз или чтение всех), то все в порядке! // // Эта функция вызовет `expensive_computation` только один раз и будет // всегда возвращать значение, возвращенное при первом вызове. fn get_cached_val() -> usize { unsafe { INIT.call_once(|| { VAL = expensive_computation(); }); VAL } } fn expensive_computation() -> usize { // ... } }
Паника
Замыкание f будет выполнено только один раз, даже если этот метод вызывается конкурентно из многих потоков. Однако, если это замыкание паникует, то оно отравит этот экземпляр Once, вызывая панику всех будущих вызовов call_once.
Это похоже на отравление мьютексами, но этот механизм гарантированно никогда не пропускает паники внутри f.
call_once_force
#![allow(unused)] fn main() { pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState), }
1.51.0
Выполняет ту же функцию, что и call_once(), но игнорирует отравление.
В отличие от call_once(), если этот Once был отравлен (т.е. предыдущий вызов call_once() или call_once_force() вызвал панику), вызов call_once_force() все равно вызовет замыкание f и не приведет к немедленной панике. Если f паникует, Once останется в отравленном состоянии. Если f не паникует, Once больше не будет в отравленном состоянии, и все будущие вызовы call_once() или call_once_force() будут no-ops.
Замыканию f передается структура OnceState, которая может быть использована для запроса статуса отравления Once.
Примеры
#![allow(unused)] fn main() { use std::sync::Once; use std::thread; static INIT: Once = Once::new(); // отравить once let handle = thread::spawn(|| { INIT.call_once(|| panic!()); }); assert!(handle.join().is_err()); // отравление распространяется let handle = thread::spawn(|| { INIT.call_once(|| {}); }); assert!(handle.join().is_err()); // call_once_force все равно выполнится и сбросит отравленное состояние INIT.call_once_force(|state| { assert!(state.is_poisoned()); }); // как только происходит любой успех, мы перестаем распространять отравление INIT.call_once(|| {}); }
is_completed
#![allow(unused)] fn main() { pub fn is_completed(&self) -> bool }
1.43.0
Возвращает true, если некоторый вызов call_once() завершился успешно. В частности, is_completed вернет false в следующих ситуациях:
call_once()не вызывался вообще,call_once()был вызван, но еще не завершился,- экземпляр
Onceотравлен
Возврат этой функцией false не означает, что Once не был выполнен. Например, он мог быть выполнен во время между началом выполнения is_completed и ее возвратом, в этом случае возвращаемое значение false было бы устаревшим (но все еще допустимым).
Примеры
#![allow(unused)] fn main() { use std::sync::Once; static INIT: Once = Once::new(); assert_eq!(INIT.is_completed(), false); INIT.call_once(|| { assert_eq!(INIT.is_completed(), false); }); assert_eq!(INIT.is_completed(), true); }
#![allow(unused)] fn main() { use std::sync::Once; use std::thread; static INIT: Once = Once::new(); assert_eq!(INIT.is_completed(), false); let handle = thread::spawn(|| { INIT.call_once(|| panic!()); }); assert!(handle.join().is_err()); assert_eq!(INIT.is_completed(), false); }
wait
#![allow(unused)] fn main() { pub fn wait(&self) }
1.86.0
Блокирует текущий поток до завершения инициализации.
Пример
#![allow(unused)] fn main() { use std::sync::Once; use std::thread; static READY: Once = Once::new(); let thread = thread::spawn(|| { READY.wait(); println!("everything is ready"); }); READY.call_once(|| println!("performing setup")); }
Паника
Если этот Once был отравлен из-за паники замыкания инициализации, этот метод также вызовет панику. Используйте wait_force, если такое поведение нежелательно.
wait_force
#![allow(unused)] fn main() { pub fn wait_force(&self) }
1.86.0
Блокирует текущий поток до завершения инициализации, игнорируя отравление.
Если этот Once был отравлен, эта функция блокируется до тех пор, пока он не станет завершенным, в отличие от Once::wait(), которая паникует в этом случае.
Реализации трейтов
Debug
1.16.0
#![allow(unused)] fn main() { impl Debug for Once }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result }
Форматирует значение с помощью заданного форматировщика.
RefUnwindSafe
1.59.0
#![allow(unused)] fn main() { impl RefUnwindSafe for Once }
UnwindSafe
1.59.0
#![allow(unused)] fn main() { impl UnwindSafe for Once }
Автоматические реализации трейтов
!Freeze
#![allow(unused)] fn main() { impl !Freeze for Once }
Send
#![allow(unused)] fn main() { impl Send for Once }
Sync
#![allow(unused)] fn main() { impl Sync for Once }
Unpin
#![allow(unused)] fn main() { impl Unpin for Once }
Стандартные реализации
(Реализации стандартных трейтов для всех типов остаются без изменений)
Структура OnceLock<T>
#![allow(unused)] fn main() { pub struct OnceLock<T> { /* приватные поля */ } }
1.70.0 · Источник
Описание
Примитив синхронизации, который номинально может быть записан только один раз.
Этот тип является потокобезопасным OnceCell и может использоваться в статических переменных. Во многих простых случаях вы можете использовать LazyLock<T, F> вместо этого, чтобы получить преимущества этого типа с меньшими усилиями: LazyLock<T, F> "выглядит как" &T, потому что он инициализируется с помощью F при разыменовании! OnceLock проявляет себя там, где LazyLock слишком прост для поддержки данного случая, так как LazyLock не позволяет передавать дополнительные входные данные в свою функцию после вызова LazyLock::new(|| ...).
OnceLock можно рассматривать как безопасную абстракцию над неинициализированными данными, которые становятся инициализированными после записи.
В отличие от Mutex, OnceLock никогда не отравляется при панике.
Примеры
Запись в OnceLock из отдельного потока:
#![allow(unused)] fn main() { use std::sync::OnceLock; static CELL: OnceLock<usize> = OnceLock::new(); // `OnceLock` еще не был записан. assert!(CELL.get().is_none()); // Создаем поток и записываем в `OnceLock`. std::thread::spawn(|| { let value = CELL.get_or_init(|| 12345); assert_eq!(value, &12345); }) .join() .unwrap(); // `OnceLock` теперь содержит значение. assert_eq!( CELL.get(), Some(&12345), ); }
Вы можете использовать OnceLock для реализации типа, который требует логики "только для добавления":
#![allow(unused)] fn main() { use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}}; use std::thread; struct OnceList<T> { data: OnceLock<T>, next: OnceLock<Box<OnceList<T>>>, } impl<T> OnceList<T> { const fn new() -> OnceList<T> { OnceList { data: OnceLock::new(), next: OnceLock::new() } } fn push(&self, value: T) { // FIXME: эта реализация лаконична, но также медленна для длинных списков или многих потоков. // в качестве упражнения, подумайте, как вы могли бы улучшить ее, сохраняя поведение if let Err(value) = self.data.set(value) { let next = self.next.get_or_init(|| Box::new(OnceList::new())); next.push(value) }; } fn contains(&self, example: &T) -> bool where T: PartialEq, { self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| { self.next.get().map(|next| next.contains(example)).unwrap_or(false) }) } } // Давайте протестируем этот новый синхронизированный список только для добавления, выполнив небольшой подсчет static LIST: OnceList<u32> = OnceList::new(); static COUNTER: AtomicU32 = AtomicU32::new(0); const LEN: u32 = 1000; thread::scope(|s| { for _ in 0..thread::available_parallelism().unwrap().get() { s.spawn(|| { while let i @ 0..LEN = COUNTER.fetch_add(1, Ordering::Relaxed) { LIST.push(i); } }); } }); for i in 0..LEN { assert!(LIST.contains(&i)); } }
Методы
new
#![allow(unused)] fn main() { pub const fn new() -> OnceLock<T> }
1.70.0 (const: 1.70.0)
Создает новую неинициализированную ячейку.
get
#![allow(unused)] fn main() { pub fn get(&self) -> Option<&T> }
1.70.0
Получает ссылку на базовое значение.
Возвращает None, если ячейка не инициализирована или находится в процессе инициализации. Этот метод никогда не блокируется.
get_mut
#![allow(unused)] fn main() { pub fn get_mut(&mut self) -> Option<&mut T> }
1.70.0
Получает изменяемую ссылку на базовое значение.
Возвращает None, если ячейка не инициализирована.
Этот метод никогда не блокируется. Поскольку он заимствует OnceLock изменяемо, статически гарантируется, что никаких активных заимствований OnceLock не существует, включая заимствования из других потоков.
wait
#![allow(unused)] fn main() { pub fn wait(&self) -> &T }
1.86.0
Блокирует текущий поток до инициализации ячейки.
Пример
Ожидание завершения вычисления в другом потоке:
#![allow(unused)] fn main() { use std::thread; use std::sync::OnceLock; let value = OnceLock::new(); thread::scope(|s| { s.spawn(|| value.set(1 + 1)); let result = value.wait(); assert_eq!(result, &2); }) }
set
#![allow(unused)] fn main() { pub fn set(&self, value: T) -> Result<(), T> }
1.70.0
Инициализирует содержимое ячейки значением value.
Может блокироваться, если другой поток в настоящее время пытается инициализировать ячейку. Гарантируется, что ячейка будет содержать значение, когда set вернет управление, хотя не обязательно то, которое было предоставлено.
Возвращает Ok(()), если ячейка была неинициализирована, и Err(value), если ячейка уже была инициализирована.
Примеры
use std::sync::OnceLock; static CELL: OnceLock<i32> = OnceLock::new(); fn main() { assert!(CELL.get().is_none()); std::thread::spawn(|| { assert_eq!(CELL.set(92), Ok(())); }).join().unwrap(); assert_eq!(CELL.set(62), Err(62)); assert_eq!(CELL.get(), Some(&92)); }
try_insert
#![allow(unused)] fn main() { pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> }
🔬 Это экспериментальное API только для ночных сборок. (once_cell_try_insert #116693)
Инициализирует содержимое ячейки значением value, если ячейка была неинициализирована, затем возвращает ссылку на него.
Может блокироваться, если другой поток в настоящее время пытается инициализировать ячейку. Гарантируется, что ячейка будет содержать значение, когда try_insert вернет управление, хотя не обязательно то, которое было предоставлено.
Возвращает Ok(&value), если ячейка была неинициализирована, и Err((¤t_value, value)), если она уже была инициализирована.
Примеры
#![feature(once_cell_try_insert)] use std::sync::OnceLock; static CELL: OnceLock<i32> = OnceLock::new(); fn main() { assert!(CELL.get().is_none()); std::thread::spawn(|| { assert_eq!(CELL.try_insert(92), Ok(&92)); }).join().unwrap(); assert_eq!(CELL.try_insert(62), Err((&92, 62))); assert_eq!(CELL.get(), Some(&92)); }
get_or_init
#![allow(unused)] fn main() { pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T, }
1.70.0
Получает содержимое ячейки, инициализируя его с помощью f(), если ячейка была неинициализирована.
Многие потоки могут вызывать get_or_init конкурентно с разными инициализирующими функциями, но гарантируется, что только одна функция будет выполнена, если функция не паникует.
Паника
Если f() паникует, паника распространяется на вызывающую сторону, и ячейка остается неинициализированной.
Ошибкой является реентерабельная инициализация ячейки из f. Точный результат не указан. Текущая реализация приводит к взаимной блокировке, но это может быть изменено на панику в будущем.
Примеры
#![allow(unused)] fn main() { use std::sync::OnceLock; let cell = OnceLock::new(); let value = cell.get_or_init(|| 92); assert_eq!(value, &92); let value = cell.get_or_init(|| unreachable!()); assert_eq!(value, &92); }
get_mut_or_init
#![allow(unused)] fn main() { pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T where F: FnOnce() -> T, }
🔬 Это экспериментальное API только для ночных сборок. (once_cell_get_mut #121641)
Получает изменяемую ссылку на содержимое ячейки, инициализируя его с помощью f(), если ячейка была неинициализирована.
Этот метод никогда не блокируется. Поскольку он заимствует OnceLock изменяемо, статически гарантируется, что никаких активных заимствований OnceLock не существует, включая заимствования из других потоков.
Паника
Если f() паникует, паника распространяется на вызывающую сторону, и ячейка остается неинициализированной.
Примеры
#![allow(unused)] #![feature(once_cell_get_mut)] fn main() { use std::sync::OnceLock; let mut cell = OnceLock::new(); let value = cell.get_mut_or_init(|| 92); assert_eq!(*value, 92); *value += 2; assert_eq!(*value, 94); let value = cell.get_mut_or_init(|| unreachable!()); assert_eq!(*value, 94); }
get_or_try_init
#![allow(unused)] fn main() { pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>, }
🔬 Это экспериментальное API только для ночных сборок. (once_cell_try #109737)
Получает содержимое ячейки, инициализируя его с помощью f(), если ячейка была неинициализирована. Если ячейка была неинициализирована и f() завершилась неудачей, возвращается ошибка.
Паника
Если f() паникует, паника распространяется на вызывающую сторону, и ячейка остается неинициализированной.
Ошибкой является реентерабельная инициализация ячейки из f. Точный результат не указан. Текущая реализация приводит к взаимной блокировке, но это может быть изменено на панику в будущем.
Примеры
#![allow(unused)] #![feature(once_cell_try)] fn main() { use std::sync::OnceLock; let cell = OnceLock::new(); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert!(cell.get().is_none()); let value = cell.get_or_try_init(|| -> Result<i32, ()> { Ok(92) }); assert_eq!(value, Ok(&92)); assert_eq!(cell.get(), Some(&92)) }
get_mut_or_try_init
#![allow(unused)] fn main() { pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E> where F: FnOnce() -> Result<T, E>, }
🔬 Это экспериментальное API только для ночных сборок. (once_cell_get_mut #121641)
Получает изменяемую ссылку на содержимое ячейки, инициализируя его с помощью f(), если ячейка была неинициализирована. Если ячейка была неинициализирована и f() завершилась неудачей, возвращается ошибка.
Этот метод никогда не блокируется. Поскольку он заимствует OnceLock изменяемо, статически гарантируется, что никаких активных заимствований OnceLock не существует, включая заимствования из других потоков.
Паника
Если f() паникует, паника распространяется на вызывающую сторону, и ячейка остается неинициализированной.
Примеры
#![allow(unused)] #![feature(once_cell_get_mut)] fn main() { use std::sync::OnceLock; let mut cell: OnceLock<u32> = OnceLock::new(); // Неудачные попытки инициализировать ячейку не изменяют ее содержимое assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err()); assert!(cell.get().is_none()); let value = cell.get_mut_or_try_init(|| "1234".parse()); assert_eq!(value, Ok(&mut 1234)); *value.unwrap() += 2; assert_eq!(cell.get(), Some(&1236)) }
into_inner
#![allow(unused)] fn main() { pub fn into_inner(self) -> Option<T> }
1.70.0
Потребляет OnceLock, возвращая обернутое значение. Возвращает None, если ячейка была неинициализирована.
Примеры
#![allow(unused)] fn main() { use std::sync::OnceLock; let cell: OnceLock<String> = OnceLock::new(); assert_eq!(cell.into_inner(), None); let cell = OnceLock::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); }
take
#![allow(unused)] fn main() { pub fn take(&mut self) -> Option<T> }
1.70.0
Извлекает значение из этого OnceLock, возвращая его в неинициализированное состояние.
Не оказывает эффекта и возвращает None, если OnceLock был неинициализирован.
Поскольку этот метод заимствует OnceLock изменяемо, статически гарантируется, что никаких активных заимствований OnceLock не существует, включая заимствования из других потоков.
Примеры
#![allow(unused)] fn main() { use std::sync::OnceLock; let mut cell: OnceLock<String> = OnceLock::new(); assert_eq!(cell.take(), None); let mut cell = OnceLock::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.take(), Some("hello".to_string())); assert_eq!(cell.get(), None); }
Реализации трейтов
Clone
1.70.0
#![allow(unused)] fn main() { impl<T: Clone> Clone for OnceLock<T> }
clone
#![allow(unused)] fn main() { fn clone(&self) -> OnceLock<T> }
Возвращает дубликат значения.
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Self) }
1.0.0
Выполняет копирующее присваивание из source.
Debug
1.70.0
#![allow(unused)] fn main() { impl<T: Debug> Debug for OnceLock<T> }
fmt
#![allow(unused)] fn main() { fn fmt(&self, f: &mut Formatter<'_>) -> Result }
Форматирует значение с помощью заданного форматировщика.
Default
1.70.0
#![allow(unused)] fn main() { impl<T> Default for OnceLock<T> }
default
#![allow(unused)] fn main() { fn default() -> OnceLock<T> }
Создает новую неинициализированную ячейку.
Пример
use std::sync::OnceLock; fn main() { assert_eq!(OnceLock::<()>::new(), OnceLock::default()); }
Drop
1.70.0
#![allow(unused)] fn main() { impl<T> Drop for OnceLock<T> }
drop
#![allow(unused)] fn main() { fn drop(&mut self) }
Выполняет деструктор для этого типа.
From<T>
1.70.0
#![allow(unused)] fn main() { impl<T> From<T> for OnceLock<T> }
from
#![allow(unused)] fn main() { fn from(value: T) -> Self }
Создает новую ячейку с содержимым, установленным в value.
Пример
#![allow(unused)] fn main() { use std::sync::OnceLock; let a = OnceLock::from(3); let b = OnceLock::new(); b.set(3)?; assert_eq!(a, b); Ok(()) }
PartialEq
1.70.0
#![allow(unused)] fn main() { impl<T: PartialEq> PartialEq for OnceLock<T> }
eq
#![allow(unused)] fn main() { fn eq(&self, other: &OnceLock<T>) -> bool }
Равенство для двух OnceLock.
Два OnceLock равны, если они либо оба содержат значения и их значения равны, либо если ни один не содержит значения.
Примеры
#![allow(unused)] fn main() { use std::sync::OnceLock; let five = OnceLock::new(); five.set(5).unwrap(); let also_five = OnceLock::new(); also_five.set(5).unwrap(); assert!(five == also_five); assert!(OnceLock::<u32>::new() == OnceLock::<u32>::new()); }
ne
#![allow(unused)] fn main() { fn ne(&self, other: &Rhs) -> bool }
1.0.0
Тестирует !=. Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины.
Eq
1.70.0
#![allow(unused)] fn main() { impl<T: Eq> Eq for OnceLock<T> }
RefUnwindSafe
1.70.0
#![allow(unused)] fn main() { impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> }
Send
1.70.0
#![allow(unused)] fn main() { impl<T: Send> Send for OnceLock<T> }
Sync
1.70.0
#![allow(unused)] fn main() { impl<T: Sync + Send> Sync for OnceLock<T> }
UnwindSafe
1.70.0
#![allow(unused)] fn main() { impl<T: UnwindSafe> UnwindSafe for OnceLock<T> }
Автоматические реализации трейтов
!Freeze
#![allow(unused)] fn main() { impl<T> !Freeze for OnceLock<T> }
Unpin
#![allow(unused)] fn main() { impl<T> Unpin for OnceLock<T> where T: Unpin, }
Стандартные реализации
(Реализации стандартных трейтов для всех типов остаются без изменений)
Структура OnceState
Описание: Состояние, передаваемое в параметр замыкания Once::call_once_force(). Это состояние можно использовать для проверки статуса отравления (poison status) Once.
Стабильность: 1.0.0
Методы
is_poisoned (стабильность: 1.51.0)
#![allow(unused)] fn main() { pub fn is_poisoned(&self) -> bool }
Возвращает true, если связанный Once был отравлен до вызова замыкания, переданного в Once::call_once_force().
Примеры
Отравленный Once:
#![allow(unused)] fn main() { use std::sync::Once; use std::thread; static INIT: Once = Once::new(); // отравляем once let handle = thread::spawn(|| { INIT.call_once(|| panic!()); }); assert!(handle.join().is_err()); INIT.call_once_force(|state| { assert!(state.is_poisoned()); }); }
Неотравленный Once:
#![allow(unused)] fn main() { use std::sync::Once; static INIT: Once = Once::new(); INIT.call_once_force(|state| { assert!(!state.is_poisoned()); }); }
Реализации трейтов
Debug (стабильность: 1.16.0)
Реализует форматирование для отладки.
Автоматические реализации трейтов
!Freeze!RefUnwindSafeSend!SyncUnpinUnwindSafe
Стандартные реализации
AnyBorrow<T>BorrowMut<T>From<T>Into<U>TryFrom<U>TryInto<U>
Структура PoisonError<T>
Описание: Тип ошибки, который может возвращаться при получении блокировки.
И Mutex, и RwLock становятся "отравленными" (poisoned), когда поток завершается с ошибкой во время удержания блокировки. Точная семантика отравления блокировки документирована для каждого типа блокировки. Для блокировки в отравленном состоянии, если состояние не очищено вручную, все последующие попытки получения блокировки будут возвращать эту ошибку.
Стабильность: 1.0.0
Примеры
#![allow(unused)] fn main() { use std::sync::{Arc, Mutex}; use std::thread; let mutex = Arc::new(Mutex::new(1)); // отравляем мьютекс let c_mutex = Arc::clone(&mutex); let _ = thread::spawn(move || { let mut data = c_mutex.lock().unwrap(); *data = 2; panic!(); }).join(); match mutex.lock() { Ok(_) => unreachable!(), Err(p_err) => { let data = p_err.get_ref(); println!("recovered: {data}"); } }; }
Методы
new (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn new(data: T) -> PoisonError<T> }
Создает PoisonError.
Обычно создается методами типа Mutex::lock или RwLock::read.
Доступно только с panic=unwind
into_inner (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn into_inner(self) -> T }
Потребляет эту ошибку, указывающую на отравленную блокировку, возвращая связанные данные.
Пример:
#![allow(unused)] fn main() { use std::collections::HashSet; use std::sync::{Arc, Mutex}; use std::thread; let mutex = Arc::new(Mutex::new(HashSet::new())); // отравляем мьютекс let c_mutex = Arc::clone(&mutex); let _ = thread::spawn(move || { let mut data = c_mutex.lock().unwrap(); data.insert(10); panic!(); }).join(); let p_err = mutex.lock().unwrap_err(); let data = p_err.into_inner(); println!("recovered {} items", data.len()); }
get_ref (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn get_ref(&self) -> &T }
Получает ссылку на связанные данные в этой ошибке, указывающей на отравленную блокировку.
get_mut (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn get_mut(&mut self) -> &mut T }
Получает изменяемую ссылку на связанные данные в этой ошибке, указывающей на отравленную блокировку.
Реализации трейтов
Debug (стабильность: 1.0.0)
Реализует форматирование для отладки.
Display (стабильность: 1.0.0)
Реализует форматирование для пользовательского отображения.
Error (стабильность: 1.0.0)
Реализует трейт ошибки.
Методы:
source()(1.30.0) - возвращает низкоуровневый источник ошибкиdescription()(1.0.0, устарел с 1.42.0) - используйте Display impl или to_string()cause()(1.0.0, устарел с 1.33.0) - заменен на Error::sourceprovide()(экспериментальный) - предоставляет доступ к контексту на основе типа
From<PoisonError<T>> for TryLockError<T> (стабильность: 1.0.0)
Преобразует PoisonError<T> в TryLockError<T>.
Автоматические реализации трейтов
Freeze(где T: Freeze)RefUnwindSafe(где T: RefUnwindSafe)Send(где T: Send)Sync(где T: Sync)Unpin(где T: Unpin)UnwindSafe(где T: UnwindSafe)
Стандартные реализации
AnyBorrow<T>BorrowMut<T>From<T>Into<U>ToStringTryFrom<U>TryInto<U>
Структура RwLock
Описание: Блокировка "читатель-писатель" (reader-writer lock)
Этот тип блокировки позволяет нескольким читателям или не более чем одному писателю в любой момент времени. Часть записи этой блокировки обычно позволяет изменять базовые данные (эксклюзивный доступ), а часть чтения обычно позволяет только чтение (разделяемый доступ).
В отличие от Mutex, который не различает читателей и писателей, блокируя все потоки, ожидающие освобождения блокировки, RwLock позволяет любому количеству читателей получить блокировку, пока писатель не удерживает её.
Политика приоритетов блокировки зависит от реализации базовой операционной системы, и этот тип не гарантирует использование какой-либо конкретной политики.
Стабильность: 1.0.0
Отравление (Poisoning)
RwLock, как и Mutex, обычно становится "отравленным" при панике. Однако RwLock может быть отравлен только если паника происходит во время эксклюзивной блокировки (режим записи). Если паника происходит в любом читателе, блокировка не будет отравлена.
Примеры
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(5); // множество блокировок чтения может удерживаться одновременно { let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); assert_eq!(*r1, 5); assert_eq!(*r2, 5); } // блокировки чтения снимаются здесь // только одна блокировка записи может удерживаться { let mut w = lock.write().unwrap(); *w += 1; assert_eq!(*w, 6); } // блокировка записи снимается здесь }
Методы
new (стабильность: 1.0.0, const с 1.63.0)
#![allow(unused)] fn main() { pub const fn new(t: T) -> RwLock<T> }
Создает новый экземпляр RwLock<T> в разблокированном состоянии.
get_cloned (экспериментальный)
#![allow(unused)] fn main() { pub fn get_cloned(&self) -> Result<T, PoisonError<()>> }
Возвращает содержащееся значение путем его клонирования.
Ошибки: Возвращает ошибку, если RwLock отравлен.
set (экспериментальный)
#![allow(unused)] fn main() { pub fn set(&self, value: T) -> Result<(), PoisonError<T>> }
Устанавливает содержащееся значение.
Ошибки: Возвращает ошибку, содержащую предоставленное value, если RwLock отравлен.
replace (экспериментальный)
#![allow(unused)] fn main() { pub fn replace(&self, value: T) -> LockResult<T> }
Заменяет содержащееся значение на value и возвращает старое значение.
Ошибки: Возвращает ошибку, содержащую предоставленное value, если RwLock отравлен.
impl<T: ?Sized> RwLock<T>
read (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> }
Блокирует этот RwLock с разделяемым доступом на чтение, блокируя текущий поток до получения доступа.
Возвращает RAII-гард, который снимет разделяемый доступ при удалении.
Ошибки: Возвращает ошибку, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(1)); let c_lock = Arc::clone(&lock); let n = lock.read().unwrap(); assert_eq!(*n, 1); thread::spawn(move || { let r = c_lock.read(); assert!(r.is_ok()); }).join().unwrap(); }
try_read (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> }
Пытается получить этот RwLock с разделяемым доступом на чтение.
Не блокирует поток. Возвращает WouldBlock, если блокировка уже захвачена эксклюзивно.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); match lock.try_read() { Ok(n) => assert_eq!(*n, 1), Err(_) => unreachable!(), }; }
write (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> }
Блокирует этот RwLock с эксклюзивным доступом на запись, блокируя текущий поток до получения доступа.
Возвращает RAII-гард, который снимет доступ на запись при удалении.
Ошибки: Возвращает ошибку, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); let mut n = lock.write().unwrap(); *n = 2; assert!(lock.try_read().is_err()); }
try_write (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> }
Пытается заблокировать этот RwLock с эксклюзивным доступом на запись.
Не блокирует поток. Возвращает WouldBlock, если блокировка уже захвачена.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); let n = lock.read().unwrap(); assert_eq!(*n, 1); assert!(lock.try_write().is_err()); }
is_poisoned (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn is_poisoned(&self) -> bool }
Определяет, отравлена ли блокировка.
Не следует доверять значению false для корректности программы без дополнительной синхронизации.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(0)); let c_lock = Arc::clone(&lock); let _ = thread::spawn(move || { let _lock = c_lock.write().unwrap(); panic!(); // the lock gets poisoned }).join(); assert_eq!(lock.is_poisoned(), true); }
clear_poison (стабильность: 1.77.0)
#![allow(unused)] fn main() { pub fn clear_poison(&self) }
Очищает отравленное состояние блокировки.
Позволяет восстановиться из отравленного состояния и отметить это.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(0)); let c_lock = Arc::clone(&lock); let _ = thread::spawn(move || { let _lock = c_lock.write().unwrap(); panic!(); // the lock gets poisoned }).join(); assert_eq!(lock.is_poisoned(), true); let guard = lock.write().unwrap_or_else(|mut e| { **e.get_mut() = 1; lock.clear_poison(); e.into_inner() }); assert_eq!(lock.is_poisoned(), false); assert_eq!(*guard, 1); }
into_inner (стабильность: 1.6.0)
#![allow(unused)] fn main() { pub fn into_inner(self) -> LockResult<T> }
Потребляет этот RwLock, возвращая базовые данные.
Ошибки: Возвращает ошибку, содержащую базовые данные, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(String::new()); { let mut s = lock.write().unwrap(); *s = "modified".to_owned(); } assert_eq!(lock.into_inner().unwrap(), "modified"); }
get_mut (стабильность: 1.6.0)
#![allow(unused)] fn main() { pub fn get_mut(&mut self) -> LockResult<&mut T> }
Возвращает изменяемую ссылку на базовые данные.
Не требует фактической блокировки, так как заимствует RwLock изменяемо.
#![allow(unused)] fn main() { use std::sync::RwLock; let mut lock = RwLock::new(0); *lock.get_mut().unwrap() = 10; assert_eq!(*lock.read().unwrap(), 10); }
data_ptr (экспериментальный)
#![allow(unused)] fn main() { pub const fn data_ptr(&self) -> *mut T }
Возвращает сырой указатель на базовые данные.
Пользователь несет ответственность за правильную синхронизацию операций чтения/записи.
Реализации трейтов
Debug (стабильность: 1.0.0)
Реализует форматирование для отладки (где T: Debug).
Default (стабильность: 1.10.0)
Создает новый RwLock<T> со значением по умолчанию для T (где T: Default).
From<T> (стабильность: 1.24.0)
Создает новый экземпляр RwLock<T> в разблокированном состоянии. Эквивалентно RwLock::new.
Безопасность потоков
Send(где T: Send)Sync(где T: Send + Sync)RefUnwindSafeUnwindSafe
Автоматические реализации трейтов
!FreezeUnpin(где T: Unpin)
Стандартные реализации
AnyBorrow<T>BorrowMut<T>From<!>From<T>Into<U>TryFrom<U>TryInto<U>
Структура RwLockReadGuard<'rwlock, T>
Описание: RAII-структура, используемая для освобождения разделяемого доступа на чтение блокировки при удалении.
Эта структура создается методами read и try_read на RwLock.
Стабильность: 1.0.0
Методы
map (экспериментальный)
#![allow(unused)] fn main() { pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U> }
Создает MappedRwLockReadGuard для компонента заимствованных данных, например, варианта перечисления.
RwLock уже заблокирован для чтения, поэтому этот метод не может завершиться неудачей.
Это ассоциированная функция, которая должна использоваться как RwLockReadGuard::map(...). Метод с таким же именем конфликтовал бы с методами содержимого RwLockReadGuard, доступными через Deref.
Паники: Если замыкание паникует, гард будет удален (разблокирован) и RwLock не будет отравлен.
filter_map (экспериментальный)
#![allow(unused)] fn main() { pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self> }
Создает MappedRwLockReadGuard для компонента заимствованных данных. Оригинальный гард возвращается как Err(...), если замыкание возвращает None.
RwLock уже заблокирован для чтения, поэтому этот метод не может завершиться неудачей.
Это ассоциированная функция, которая должна использоваться как RwLockReadGuard::filter_map(...). Метод с таким же именем конфликтовал бы с методами содержимого RwLockReadGuard, доступными через Deref.
Паники: Если замыкание паникует, гард будет удален (разблокирован) и RwLock не будет отравлен.
Реализации трейтов
Debug (стабильность: 1.16.0)
Реализует форматирование для отладки (где T: Debug).
Deref (стабильность: 1.0.0)
Реализует разыменование для доступа к защищенным данным.
Ассоциированный тип:
Target = T- тип после разыменования
Метод:
deref(&self) -> &T- разыменовывает значение
Display (стабильность: 1.20.0)
Реализует пользовательское форматирование (где T: Display).
Drop (стабильность: 1.0.0)
Реализует автоматическое освобождение блокировки при удалении гарда.
Безопасность потоков
!Send- не может быть отправлен между потокамиSync(где T: Sync) - может использоваться совместно между потоками
Автоматические реализации трейтов
FreezeRefUnwindSafe(где T: RefUnwindSafe)UnpinUnwindSafe(где T: RefUnwindSafe)
Стандартные реализации
AnyBorrow<T>BorrowMut<T>From<T>Into<U>Receiver(экспериментальный) - для произвольных типов selfToStringTryFrom<U>TryInto<U>
Структура RwLockWriteGuard
RAII-структура, используемая для освобождения эксклюзивного доступа на запись блокировки при её удалении.
Описание
Эта структура создаётся методами write и try_write на RwLock.
Методы
downgrade (стабильно с версии 1.92.0)
#![allow(unused)] fn main() { pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> }
Понижает RwLockWriteGuard с записью до RwLockReadGuard с чтением.
Поскольку у нас есть RwLockWriteGuard, RwLock уже должен быть заблокирован для записи, поэтому этот метод не может завершиться неудачей.
После понижения другим читателям будет разрешено читать защищённые данные.
Примеры:
downgrade принимает владение RwLockWriteGuard и возвращает RwLockReadGuard.
#![allow(unused)] fn main() { use std::sync::{RwLock, RwLockWriteGuard}; let rw = RwLock::new(0); let mut write_guard = rw.write().unwrap(); *write_guard = 42; let read_guard = RwLockWriteGuard::downgrade(write_guard); assert_eq!(42, *read_guard); }
downgrade атомарно изменит состояние RwLock из эксклюзивного режима в общий режим. Это означает, что другому потоку записи невозможно встать между вызовом потока downgrade и любыми операциями чтения, которые он выполняет после понижения.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock, RwLockWriteGuard}; let rw = Arc::new(RwLock::new(1)); // Переводим блокировку в режим записи. let mut main_write_guard = rw.write().unwrap(); let rw_clone = rw.clone(); let evil_handle = std::thread::spawn(move || { // Это не вернётся, пока основной поток не отпустит `main_read_guard`. let mut evil_guard = rw_clone.write().unwrap(); assert_eq!(*evil_guard, 2); *evil_guard = 3; }); *main_write_guard = 2; // Атомарно понижаем guard записи до guard чтения. let main_read_guard = RwLockWriteGuard::downgrade(main_write_guard); // Поскольку `downgrade` атомарна, поток-писатель не мог изменить защищённые данные. assert_eq!(*main_read_guard, 2, "`downgrade` was not atomic"); }
map (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U> where F: FnOnce(&mut T) -> &mut U, U: ?Sized, }
Создаёт MappedRwLockWriteGuard для компонента заимствованных данных, например, варианта перечисления.
RwLock уже заблокирован для записи, поэтому это не может завершиться неудачей.
Это ассоциированная функция, которую нужно использовать как RwLockWriteGuard::map(...). Метод будет конфликтовать с методами с тем же именем у содержимого RwLockWriteGuard, используемого через Deref.
Паника: Если замыкание запаникует, guard будет удалён (разблокирован) и RwLock будет отравлен.
filter_map (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub fn filter_map<U, F>( orig: Self, f: F, ) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>, U: ?Sized, }
Создаёт MappedRwLockWriteGuard для компонента заимствованных данных. Исходный guard возвращается как Err(...), если замыкание возвращает None.
RwLock уже заблокирован для записи, поэтому это не может завершиться неудачей.
Это ассоциированная функция, которую нужно использовать как RwLockWriteGuard::filter_map(...). Метод будет конфликтовать с методами с тем же именем у содержимого RwLockWriteGuard, используемого через Deref.
Паника: Если замыкание запаникует, guard будет удалён (разблокирован) и RwLock будет отравлен.
Реализации трейтов
Debug (стабильно с версии 1.16.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized + Debug.
Deref (стабильно с версии 1.0.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized.
- Ассоциированный тип:
Target = T - Метод:
deref(&self) -> &T
DerefMut (стабильно с версии 1.0.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized.
- Метод:
deref_mut(&mut self) -> &mut T
Display (стабильно с версии 1.20.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized + Display.
Drop (стабильно с версии 1.0.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized.
!Send
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized.
Sync (стабильно с версии 1.23.0)
Реализован для RwLockWriteGuard<'_, T>, где T: ?Sized + Sync.
Автоматические реализации трейтов
FreezeдляRwLockWriteGuard<'rwlock, T>, гдеT: ?SizedRefUnwindSafeдляRwLockWriteGuard<'rwlock, T>, гдеT: ?SizedUnpinдляRwLockWriteGuard<'rwlock, T>, гдеT: ?SizedUnwindSafeдляRwLockWriteGuard<'rwlock, T>, гдеT: ?Sized
Blanket-реализации
Стандартные blanket-реализации для всех типов, такие как Any, Borrow<T>, From<T>, ToString и другие.
Структура WaitTimeoutResult
Тип, указывающий, вернулась ли ожидание с таймаутом на переменной условия из-за истечения времени или нет.
Возвращается методом wait_timeout.
Декларация
#![allow(unused)] fn main() { pub struct WaitTimeoutResult(/* private fields */); }
Методы
timed_out (стабильно с версии 1.5.0)
#![allow(unused)] fn main() { pub fn timed_out(&self) -> bool }
Возвращает true, если известно, что ожидание завершилось по таймауту.
Примеры:
Этот пример порождает поток, который будет спать 20 миллисекунд перед обновлением логического значения и последующим уведомлением переменной условия.
Основной поток будет ждать с таймаутом 10 миллисекунд на переменной условия и выйдет из цикла по истечении таймаута.
#![allow(unused)] fn main() { use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::time::Duration; let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair2 = Arc::clone(&pair); thread::spawn(move || { let (lock, cvar) = &*pair2; // Подождём 20 миллисекунд перед уведомлением переменной условия. thread::sleep(Duration::from_millis(20)); let mut started = lock.lock().unwrap(); // Обновляем логическое значение. *started = true; cvar.notify_one(); }); // Ждём запуска потока. let (lock, cvar) = &*pair; loop { // Установим таймаут на ожидание переменной условия. let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap(); // Прошло 10 миллисекунд. if result.1.timed_out() { // Таймаут истёк, теперь можем выйти. break } } }
Реализации трейтов
Clone (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
- Метод:
clone(&self) -> WaitTimeoutResult- возвращает дубликат значения. - Метод:
clone_from(&mut self, source: &Self)- выполняет присваивание копированием изsource.
Debug (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
- Метод:
fmt(&self, f: &mut Formatter<'_>) -> Result- форматирует значение с помощью данного форматтера.
PartialEq (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
- Метод:
eq(&self, other: &WaitTimeoutResult) -> bool- проверяет равенство значенийselfиother, используется оператором==. - Метод:
ne(&self, other: &Rhs) -> bool- проверяет неравенство!=. Реализация по умолчанию почти всегда достаточна и не должна переопределяться без очень веской причины.
Copy (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
Eq (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
StructuralPartialEq (стабильно с версии 1.5.0)
Реализован для WaitTimeoutResult.
Автоматические реализации трейтов
FreezeдляWaitTimeoutResultRefUnwindSafeдляWaitTimeoutResultSendдляWaitTimeoutResultSyncдляWaitTimeoutResultUnpinдляWaitTimeoutResultUnwindSafeдляWaitTimeoutResult
Blanket-реализации
Стандартные blanket-реализации для всех типов, такие как:
AnyдляT, гдеT: 'static + ?SizedBorrow<T>дляT, гдеT: ?SizedBorrowMut<T>дляT, гдеT: ?SizedCloneToUninitдляT, гдеT: Clone(экспериментальное API)From<T>дляTInto<U>дляT, гдеU: From<T>ToOwnedдляT, гдеT: CloneTryFrom<U>дляT, гдеU: Into<T>TryInto<U>дляT, гдеU: TryFrom<T>
Структура Weak
Weak- это версияArc, которая содержит невладеющую ссылку на управляемое выделение памяти.
Описание
Выделение памяти доступно через вызов upgrade на указателе Weak, который возвращает Option<Arc<T>>.
Поскольку слабая ссылка не учитывается в праве владения, она не предотвращает удаление значения, хранящегося в выделенной памяти, и сам Weak не даёт гарантий, что значение всё ещё присутствует. Таким образом, он может вернуть None при вызове upgrade. Однако следует отметить, что слабая ссылка действительно предотвращает освобождение самой памяти (резервного хранилища).
Указатель Weak полезен для сохранения временной ссылки на выделение памяти, управляемое Arc, без предотвращения удаления его внутреннего значения. Он также используется для предотвращения циклических ссылок между указателями Arc, поскольку взаимные владеющие ссылки никогда не позволят удалить ни один из Arc. Например, дерево может иметь сильные указатели Arc от родительских узлов к дочерним и слабые указатели Weak от дочерних обратно к их родителям.
Типичный способ получить указатель Weak - вызвать Arc::downgrade.
Декларация
#![allow(unused)] fn main() { pub struct Weak<T, A = Global> where A: Allocator, T: ?Sized, { /* private fields */ } }
Методы
new (стабильно с версии 1.10.0, const с 1.73.0)
#![allow(unused)] fn main() { pub const fn new() -> Weak<T> }
Создаёт новый Weak<T> без выделения памяти. Вызов upgrade на возвращаемом значении всегда даёт None.
Примеры:
#![allow(unused)] fn main() { use std::sync::Weak; let empty: Weak<i64> = Weak::new(); assert!(empty.upgrade().is_none()); }
new_in (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub fn new_in(alloc: A) -> Weak<T, A> }
Создаёт новый Weak<T, A> без выделения памяти, технически в предоставленном аллокаторе. Вызов upgrade на возвращаемом значении всегда даёт None.
Примеры:
#![allow(unused)] #![feature(allocator_api)] fn main() { use std::sync::Weak; use std::alloc::System; let empty: Weak<i64, _> = Weak::new_in(System); assert!(empty.upgrade().is_none()); }
from_raw (стабильно с версии 1.45.0)
#![allow(unused)] fn main() { pub unsafe fn from_raw(ptr: *const T) -> Weak<T> }
Преобразует сырой указатель, ранее созданный into_raw, обратно в Weak<T>.
Это можно использовать для безопасного получения сильной ссылки (вызовом upgrade позже) или для освобождения слабого счётчика путём удаления Weak<T>.
Он принимает владение одной слабой ссылкой (за исключением указателей, созданных new, так как они ничем не владеют; метод всё равно работает с ними).
Безопасность:
Указатель должен происходить из into_raw и всё ещё должен владеть своей потенциальной слабой ссылкой, и должен указывать на блок памяти, выделенный глобальным аллокатором.
Разрешено, чтобы сильный счётчик был 0 во время вызова этого метода. Тем не менее, это принимает владение одной слабой ссылкой, в настоящее время представленной как сырой указатель (слабый счётчик не изменяется этой операцией), и поэтому он должен быть сопряжён с предыдущим вызовом into_raw.
Примеры:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; let strong = Arc::new("hello".to_owned()); let raw_1 = Arc::downgrade(&strong).into_raw(); let raw_2 = Arc::downgrade(&strong).into_raw(); assert_eq!(2, Arc::weak_count(&strong)); assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); assert_eq!(1, Arc::weak_count(&strong)); drop(strong); // Уменьшаем последний слабый счётчик. assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); }
into_raw (стабильно с версии 1.45.0)
#![allow(unused)] fn main() { pub fn into_raw(self) -> *const T }
Потребляет Weak<T> и превращает его в сырой указатель.
Это преобразует слабый указатель в сырой указатель, сохраняя владение одной слабой ссылкой (слабый счётчик не изменяется этой операцией). Его можно преобразовать обратно в Weak<T> с помощью from_raw.
Применяются те же ограничения доступа к цели указателя, что и с as_ptr.
Примеры:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; let strong = Arc::new("hello".to_owned()); let weak = Arc::downgrade(&strong); let raw = weak.into_raw(); assert_eq!(1, Arc::weak_count(&strong)); assert_eq!("hello", unsafe { &*raw }); drop(unsafe { Weak::from_raw(raw) }); assert_eq!(0, Arc::weak_count(&strong)); }
allocator (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub fn allocator(&self) -> &A }
Возвращает ссылку на базовый аллокатор.
as_ptr (стабильно с версии 1.45.0)
#![allow(unused)] fn main() { pub fn as_ptr(&self) -> *const T }
Возвращает сырой указатель на объект T, на который указывает этот Weak<T>.
Указатель действителен только при наличии некоторых сильных ссылок. В противном случае указатель может быть висящим, невыровненным или даже null.
Примеры:
#![allow(unused)] fn main() { use std::sync::Arc; use std::ptr; let strong = Arc::new("hello".to_owned()); let weak = Arc::downgrade(&strong); // Оба указывают на один и тот же объект assert!(ptr::eq(&*strong, weak.as_ptr())); // Сильная ссылка здесь сохраняет его живым, поэтому мы всё ещё можем получить доступ к объекту. assert_eq!("hello", unsafe { &*weak.as_ptr() }); drop(strong); // Но больше нет. Мы можем вызвать weak.as_ptr(), но доступ к указателю приведёт к // неопределённому поведению. // assert_eq!("hello", unsafe { &*weak.as_ptr() }); }
into_raw_with_allocator (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub fn into_raw_with_allocator(self) -> (*const T, A) }
Потребляет Weak<T>, возвращая обёрнутый указатель и аллокатор.
Это преобразует слабый указатель в сырой указатель, сохраняя владение одной слабой ссылкой (слабый счётчик не изменяется этой операцией). Его можно преобразовать обратно в Weak<T> с помощью from_raw_in.
Применяются те же ограничения доступа к цели указателя, что и с as_ptr.
Примеры:
#![allow(unused)] #![feature(allocator_api)] fn main() { use std::sync::{Arc, Weak}; use std::alloc::System; let strong = Arc::new_in("hello".to_owned(), System); let weak = Arc::downgrade(&strong); let (raw, alloc) = weak.into_raw_with_allocator(); assert_eq!(1, Arc::weak_count(&strong)); assert_eq!("hello", unsafe { &*raw }); drop(unsafe { Weak::from_raw_in(raw, alloc) }); assert_eq!(0, Arc::weak_count(&strong)); }
from_raw_in (только ночная версия, экспериментальное API)
#![allow(unused)] fn main() { pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Weak<T, A> }
Преобразует сырой указатель, ранее созданный into_raw, обратно в Weak<T> в предоставленном аллокаторе.
Это можно использовать для безопасного получения сильной ссылки (вызовом upgrade позже) или для освобождения слабого счётчика путём удаления Weak<T>.
Он принимает владение одной слабой ссылкой (за исключением указателей, созданных new, так как они ничем не владеют; метод всё равно работает с ними).
Безопасность:
Указатель должен происходить из into_raw и всё ещё должен владеть своей потенциальной слабой ссылкой, и должен указывать на блок памяти, выделенный alloc.
Разрешено, чтобы сильный счётчик был 0 во время вызова этого метода. Тем не менее, это принимает владение одной слабой ссылкой, в настоящее время представленной как сырой указатель (слабый счётчик не изменяется этой операцией), и поэтому он должен быть сопряжён с предыдущим вызовом into_raw.
upgrade (стабильно с версии 1.4.0)
#![allow(unused)] fn main() { pub fn upgrade(&self) -> Option<Arc<T, A>> where A: Clone, }
Пытается повысить указатель Weak до Arc, откладывая удаление внутреннего значения в случае успеха.
Возвращает None, если внутреннее значение с тех пор было удалено.
Примеры:
#![allow(unused)] fn main() { use std::sync::Arc; let five = Arc::new(5); let weak_five = Arc::downgrade(&five); let strong_five: Option<Arc<_>> = weak_five.upgrade(); assert!(strong_five.is_some()); // Уничтожаем все сильные указатели. drop(strong_five); drop(five); assert!(weak_five.upgrade().is_none()); }
strong_count (стабильно с версии 1.41.0)
#![allow(unused)] fn main() { pub fn strong_count(&self) -> usize }
Получает количество сильных (Arc) указателей, указывающих на это выделение памяти.
Если self был создан с помощью Weak::new, это вернёт 0.
weak_count (стабильно с версии 1.41.0)
#![allow(unused)] fn main() { pub fn weak_count(&self) -> usize }
Получает приблизительное количество указателей Weak, указывающих на это выделение памяти.
Если self был создан с помощью Weak::new, или если не осталось сильных указателей, это вернёт 0.
Точность:
Из-за особенностей реализации возвращаемое значение может отличаться на 1 в любую сторону, когда другие потоки манипулируют любыми Arc или Weak, указывающими на то же выделение памяти.
ptr_eq (стабильно с версии 1.39.0)
#![allow(unused)] fn main() { pub fn ptr_eq(&self, other: &Weak<T, A>) -> bool }
Возвращает true, если два Weak указывают на одно и то же выделение памяти, аналогично ptr::eq, или если оба не указывают ни на какое выделение памяти (потому что они были созданы с помощью Weak::new()). Однако эта функция игнорирует метаданные указателей dyn Trait.
Примечания:
Поскольку это сравнивает указатели, это означает, что Weak::new() будет равен друг другу, даже если они не указывают ни на какое выделение памяти.
Примеры:
#![allow(unused)] fn main() { use std::sync::Arc; let first_rc = Arc::new(5); let first = Arc::downgrade(&first_rc); let second = Arc::downgrade(&first_rc); assert!(first.ptr_eq(&second)); let third_rc = Arc::new(5); let third = Arc::downgrade(&third_rc); assert!(!first.ptr_eq(&third)); }
Сравнение Weak::new:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; let first = Weak::new(); let second = Weak::new(); assert!(first.ptr_eq(&second)); let third_rc = Arc::new(()); let third = Arc::downgrade(&third_rc); assert!(!first.ptr_eq(&third)); }
Реализации трейтов
Clone (стабильно с версии 1.4.0)
Реализован для Weak<T, A>, где A: Allocator + Clone, T: ?Sized.
- Метод:
clone(&self) -> Weak<T, A>- создаёт клон указателяWeak, который указывает на то же выделение памяти.
Примеры:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; let weak_five = Arc::downgrade(&Arc::new(5)); let _ = Weak::clone(&weak_five); }
Debug (стабильно с версии 1.4.0)
Реализован для Weak<T, A>, где A: Allocator, T: ?Sized.
Default (стабильно с версии 1.10.0)
Реализован для Weak<T>.
- Метод:
default() -> Weak<T>- создаёт новыйWeak<T>без выделения памяти. Вызовupgradeна возвращаемом значении всегда даётNone.
Примеры:
#![allow(unused)] fn main() { use std::sync::Weak; let empty: Weak<i64> = Default::default(); assert!(empty.upgrade().is_none()); }
Drop (стабильно с версии 1.4.0)
Реализован для Weak<T, A>, где A: Allocator, T: ?Sized.
- Метод:
drop(&mut self)- удаляет указательWeak.
Примеры:
#![allow(unused)] fn main() { use std::sync::{Arc, Weak}; struct Foo; impl Drop for Foo { fn drop(&mut self) { println!("dropped!"); } } let foo = Arc::new(Foo); let weak_foo = Arc::downgrade(&foo); let other_weak_foo = Weak::clone(&weak_foo); drop(weak_foo); // Ничего не печатает drop(foo); // Печатает "dropped!" assert!(other_weak_foo.upgrade().is_none()); }
Другие реализации трейтов
CloneFromCellдляWeak<T>, гдеT: ?SizedCoerceUnsized<Weak<U, A>>дляWeak<T, A>, гдеT: Unsize<U> + ?Sized,A: Allocator,U: ?SizedDispatchFromDyn<Weak<U>>дляWeak<T>, гдеT: Unsize<U> + ?Sized,U: ?SizedPinCoerceUnsizedдляWeak<T, A>, гдеA: Allocator,T: ?SizedSendдляWeak<T, A>, гдеT: Sync + Send + ?Sized,A: Allocator + SendSyncдляWeak<T, A>, гдеT: Sync + Send + ?Sized,A: Allocator + SyncUseClonedдляWeak<T, A>, гдеA: Allocator + Clone,T: ?Sized
Автоматические реализации трейтов
FreezeдляWeak<T, A>, гдеA: Freeze,T: ?SizedRefUnwindSafeдляWeak<T, A>, гдеA: RefUnwindSafe,T: RefUnwindSafe + ?SizedUnpinдляWeak<T, A>, гдеA: Unpin,T: ?SizedUnwindSafeдляWeak<T, A>, гдеA: UnwindSafe,T: RefUnwindSafe + ?Sized
Blanket-реализации
Стандартные blanket-реализации для всех типов, такие как Any, Borrow<T>, From<T>, ToString и другие.
Модули
mpsc
atomic
Типы Алиасы
TryLockError
Модуль task
Типы и трейты для работы с асинхронными задачами.
Макросы
ready
Извлекает успешный тип из Poll<T>.
Структуры
Context
Контекст асинхронной задачи.
RawWaker
RawWaker позволяет разработчику исполнителя задач создавать Waker или LocalWaker, которые предоставляют настраиваемое поведение пробуждения.
RawWakerVTable
Таблица виртуальных указателей функций (vtable), которая определяет поведение RawWaker.
Waker
Waker - это дескриптор для пробуждения задачи путем уведомления ее исполнителя о том, что она готова к выполнению.
ContextBuilder
Экспериментальный
Строитель, используемый для создания экземпляра Context с поддержкой LocalWaker.
LocalWaker
Экспериментальный
LocalWaker аналогичен Waker, но не реализует Send или Sync.
Перечисления
Poll
Указывает, доступно ли значение или текущая задача была запланирована для получения пробуждения.
Трейты
Wake
Реализация пробуждения задачи в исполнителе.
LocalWake
Экспериментальный
Аналогичный трейт Wake, но используемый для создания LocalWaker.
Macros
Макрос ready!
Описание
Макрос ready! извлекает успешное значение из Poll<T> и обеспечивает распространение сигналов Pending путем досрочного возврата.
Синтаксис
#![allow(unused)] fn main() { ready!(expression) }
Параметры
expression- выражение, возвращающееPoll<T>
Возвращаемое значение
- Если выражение возвращает
Poll::Ready(t), макрос возвращаетt - Если выражение возвращает
Poll::Pending, макрос выполняетreturn Poll::Pending
Пример использования
#![allow(unused)] fn main() { use std::task::{ready, Context, Poll}; use std::future::{self, Future}; use std::pin::Pin; pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { let mut fut = future::ready(42); let fut = Pin::new(&mut fut); let num = ready!(fut.poll(cx)); // ... использование num Poll::Ready(()) } }
Раскрытие макроса
Вызов ready! раскрывается в следующий код:
#![allow(unused)] fn main() { let num = match fut.poll(cx) { Poll::Ready(t) => t, Poll::Pending => return Poll::Pending, }; }
Когда использовать
Используйте макрос ready! когда вам нужно:
- Извлечь значение из
Poll::Ready - Автоматически обработать
Poll::Pendingс возвратом - Упростить код с цепочкой асинхронных операций
Примечания
- Макрос определен в модуле
std::task - Доступен начиная с Rust 1.64.0
- Часто используется в реализации Future-трайтов
Struct
Структура Context<'a>
Описание
Контекст асинхронной задачи.
В настоящее время Context предоставляет доступ к &Waker, который может быть использован для пробуждения текущей задачи.
Синтаксис
#![allow(unused)] fn main() { pub struct Context<'a> { /* приватные поля */ } }
Методы
from_waker
#![allow(unused)] fn main() { pub const fn from_waker(waker: &'a Waker) -> Context<'a> }
Создает новый Context из &Waker.
Доступность: 1.36.0 (const: 1.82.0)
waker
#![allow(unused)] fn main() { pub const fn waker(&self) -> &'a Waker }
Возвращает ссылку на Waker для текущей задачи.
Доступность: 1.36.0 (const: 1.82.0)
local_waker ⚡️
#![allow(unused)] fn main() { pub const fn local_waker(&self) -> &'a LocalWaker }
Возвращает ссылку на LocalWaker для текущей задачи.
Примечание: Это экспериментальное API, доступно только в ночных сборках Rust.
ext ⚡️
#![allow(unused)] fn main() { pub const fn ext(&mut self) -> &mut (dyn Any + 'static) }
Возвращает ссылку на данные расширения для текущей задачи.
Примечание: Это экспериментальное API, доступно только в ночных сборках Rust.
Реализации трейтов
Debug
#![allow(unused)] fn main() { impl Debug for Context<'_> }
Позволяет форматирование Context для отладки.
Автоматические реализации трейтов
Freeze for Context<'a>- может быть замороженRefUnwindSafe for Context<'a>- безопасен для паники!Send for Context<'a>- не может быть передан между потоками!Sync for Context<'a>- не может быть разделен между потокамиUnpin for Context<'a>- может быть безопасно перемещеноUnwindSafe for Context<'a>- безопасен для паники
Пример использования
#![allow(unused)] fn main() { use std::task::{Context, Poll, Waker}; // Создание контекста из Waker let waker: &Waker = ...; let cx = Context::from_waker(waker); // Получение Waker из контекста let waker_ref = cx.waker(); }
Назначение
Context используется в асинхронном программировании Rust для:
- Предоставления доступа к
Wakerдля пробуждения задач - Передачи контекстной информации в асинхронные операции
- Реализации Future-трейтов
Особенности
- Не является
SendилиSync, так как привязан к конкретному исполнению - Содержит время жизни
'a, связанное с временем жизни Waker - Используется в методах
pollFuture-трейтов
Структура RawWaker
Описание
RawWaker позволяет разработчику исполнителя задач создать Waker или LocalWaker, которые предоставляют кастомное поведение пробуждения.
Состоит из указателя данных и таблицы виртуальных функций (vtable), которая настраивает поведение RawWaker.
Использование RawWaker небезопасно. Реализация трейта Wake является безопасной альтернативой, но требует выделения памяти.
Синтаксис
#![allow(unused)] fn main() { pub struct RawWaker { /* приватные поля */ } }
Методы
new
#![allow(unused)] fn main() { pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker }
Создает новый RawWaker из предоставленного указателя данных и vtable.
Доступность: 1.36.0 (const: 1.36.0)
Параметры
data- указатель на произвольные данные, требуемые исполнителемvtable- таблица виртуальных функций для настройки поведения
Безопасность
- Указатель данных должен указывать на потокобезопасный тип (например,
Arc<T: Send + Sync>) при созданииWaker - Это ограничение снимается при создании
LocalWaker, что позволяет использовать типы безSend + Sync(например,Rc<T>) - Vtable настраивает поведение
Waker, созданного изRawWaker
Реализации трейтов
From<Arc<W>> для RawWaker
#![allow(unused)] fn main() { impl<W> From<Arc<W>> for RawWaker where W: Wake + Send + Sync + 'static, }
Использует пробуждаемый тип как RawWaker.
Особенности:
- Не требует выделения памяти или атомарных операций
- Доступно только на платформах с
target_has_atomic=ptr
From<Rc<W>> для RawWaker
#![allow(unused)] fn main() { impl<W> From<Rc<W>> for RawWaker where W: LocalWake + 'static, }
Использует пробуждаемый тип как RawWaker.
Особенности:
- Не требует выделения памяти или атомарных операций
- Работает с типами, не реализующими
Send + Sync
Debug
#![allow(unused)] fn main() { impl Debug for RawWaker }
Позволяет форматирование RawWaker для отладки.
PartialEq
#![allow(unused)] fn main() { impl PartialEq for RawWaker }
Реализует проверку на равенство для RawWaker.
Автоматические реализации трейтов
Freeze for RawWaker- может быть замороженRefUnwindSafe for RawWaker- безопасен для паники!Send for RawWaker- не может быть передан между потоками!Sync for RawWaker- не может быть разделен между потокамиUnpin for RawWaker- может быть безопасно перемещеноUnwindSafe for RawWaker- безопасен для паники
Пример использования
#![allow(unused)] fn main() { use std::task::RawWaker; // Создание кастомного RawWaker let data: *const () = ...; let vtable: &RawWakerVTable = ...; let raw_waker = RawWaker::new(data, vtable); }
Назначение
RawWaker используется для:
- Создания кастомных исполнителей задач
- Реализации низкоуровневого поведения пробуждения
- Интеграции с внешними системами событий
Предупреждения
- Использование
RawWakerтребует небезопасного кода - Неправильная реализация может привести к неопределенному поведению
- Рекомендуется использовать безопасные альтернативы (
Wake,LocalWake) когда это возможно
Безопасность
При реализации RawWaker необходимо обеспечить:
- Корректность указателя данных
- Правильную реализацию vtable
- Потокобезопасность при использовании с
Waker - Корректное управление временем жизни данных
Структура RawWakerVTable
Описание
Таблица виртуальных функций (vtable), которая определяет поведение RawWaker.
Указатель, передаваемый во все функции внутри vtable, является указателем данных из содержащего объекта RawWaker.
Функции внутри этой структуры предназначены только для вызова на указателе данных правильно сконструированного объекта RawWaker из реализации RawWaker. Вызов одной из содержащихся функций с использованием любого другого указателя данных вызовет неопределенное поведение.
Примечание: хотя этот тип реализует PartialEq, сравнение указателей функций (и, следовательно, сравнение структур, содержащих указатели функций) ненадежно: указатели на одну и ту же функцию могут сравниваться как неравные (поскольку функции дублируются в нескольких единицах кодогенерации), а указатели на разные функции могут сравниваться как равные (поскольку идентичные функции могут быть дедуплицированы в пределах одной единицы кодогенерации).
Потокобезопасность
Если RawWaker будет использоваться для создания Waker, то все эти функции должны быть потокобезопасными (даже несмотря на то, что RawWaker является !Send + !Sync). Это связано с тем, что Waker является Send + Sync, и он может быть перемещен в произвольные потоки или вызван по ссылке &. Например, это означает, что если функции clone и drop управляют счетчиком ссылок, они должны делать это атомарно.
Однако, если RawWaker будет использоваться для создания LocalWaker, то эти функции не обязательно должны быть потокобезопасными. Это означает, что данные !Send + !Sync могут храниться в указателе данных, и подсчет ссылок не требует атомарной синхронизации. Это связано с тем, что LocalWaker сам по себе не является потокобезопасным, поэтому его нельзя передавать между потоками.
Синтаксис
#![allow(unused)] fn main() { pub struct RawWakerVTable { /* приватные поля */ } }
Методы
new
#![allow(unused)] fn main() { pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), wake_by_ref: unsafe fn(*const ()), drop: unsafe fn(*const ()), ) -> RawWakerVTable }
Создает новый RawWakerVTable из предоставленных функций clone, wake, wake_by_ref и drop.
Доступность: 1.36.0 (const: 1.36.0)
Параметры
clone- функция, вызываемая при клонированииRawWakerwake- функция, вызываемая при пробуждении задачи (потребляет данные)wake_by_ref- функция, вызываемая при пробуждении задачи (не потребляет данные)drop- функция, вызываемая при удаленииRawWaker
Безопасность
Все функции должны быть небезопасными (unsafe fn), так как они работают с сырыми указателями.
Описание функций vtable
clone
Эта функция вызывается, когда RawWaker клонируется, например, когда Waker/LocalWaker, в котором хранится RawWaker, клонируется.
Реализация этой функции должна сохранять все ресурсы, необходимые для этого дополнительного экземпляра RawWaker и связанной задачи. Вызов wake на результирующем RawWaker должен приводить к пробуждению той же задачи, которая была бы пробуждена исходным RawWaker.
wake
Эта функция вызывается, когда wake вызывается на Waker. Она должна пробуждать задачу, связанную с этим RawWaker.
Реализация этой функции должна гарантировать освобождение любых ресурсов, связанных с этим экземпляром RawWaker и связанной задачи.
wake_by_ref
Эта функция вызывается, когда wake_by_ref вызывается на Waker. Она должна пробуждать задачу, связанную с этим RawWaker.
Эта функция похожа на wake, но не должна потреблять предоставленный указатель данных.
drop
Эта функция вызывается, когда Waker/LocalWaker удаляется.
Реализация этой функции должна гарантировать освобождение любых ресурсов, связанных с этим экземпляром RawWaker и связанной задачи.
Реализации трейтов
Clone
#![allow(unused)] fn main() { impl Clone for RawWakerVTable }
Позволяет клонирование RawWakerVTable.
Debug
#![allow(unused)] fn main() { impl Debug for RawWakerVTable }
Позволяет форматирование RawWakerVTable для отладки.
PartialEq
#![allow(unused)] fn main() { impl PartialEq for RawWakerVTable }
Реализует проверку на равенство для RawWakerVTable.
Copy
#![allow(unused)] fn main() { impl Copy for RawWakerVTable }
Позволяет копирование RawWakerVTable по значению.
Автоматические реализации трейтов
Freeze for RawWakerVTable- может быть замороженRefUnwindSafe for RawWakerVTable- безопасен для паникиSend for RawWakerVTable- может быть передан между потокамиSync for RawWakerVTable- может быть разделен между потокамиUnpin for RawWakerVTable- может быть безопасно перемещеноUnwindSafe for RawWakerVTable- безопасен для паники
Пример использования
#![allow(unused)] fn main() { use std::task::{RawWaker, RawWakerVTable}; unsafe fn clone(data: *const ()) -> RawWaker { // Реализация клонирования } unsafe fn wake(data: *const ()) { // Реализация пробуждения (потребляет данные) } unsafe fn wake_by_ref(data: *const ()) { // Реализация пробуждения (не потребляет данные) } unsafe fn drop(data: *const ()) { // Реализация очистки } static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); }
Назначение
RawWakerVTable используется для:
- Определения кастомного поведения пробуждения задач
- Интеграции с внешними системами событий
- Создания специализированных исполнителей задач
Предупреждения
- Неправильная реализация может привести к неопределенному поведению
- Необходимо обеспечить корректность всех функций vtable
- Следует учитывать требования потокобезопасности в зависимости от типа создаваемого Waker
Структура Waker
Описание
Waker - это дескриптор для пробуждения задачи, уведомляющий её исполнитель о готовности к выполнению.
Этот дескриптор инкапсулирует экземпляр RawWaker, который определяет специфичное для исполнителя поведение пробуждения.
Типичный жизненный цикл Waker:
- Создается исполнителем
- Оборачивается в
Context - Передается в
Future::poll() - Если future возвращает
Poll::Pending, он должен сохранить waker и вызватьWaker::wake(), когда future нужно опросить снова
Реализует Clone, Send и Sync; следовательно, waker может быть вызван из любого потока, включая те, которые никак не управляются исполнителем. Например, это может быть сделано для пробуждения future, когда блокирующий вызов функции завершается в другом потоке.
Примечание: предпочтительнее использовать waker.clone_from(&new_waker) вместо *waker = new_waker.clone(), так как первый вариант избежит ненужного клонирования waker, если оба waker пробуждают одну и ту же задачу.
Создание Waker из RawWaker небезопасно. Реализация трейта Wake является безопасной альтернативой, но требует выделения памяти.
Синтаксис
#![allow(unused)] fn main() { pub struct Waker { /* приватные поля */ } }
Методы
wake
#![allow(unused)] fn main() { pub fn wake(self) }
Пробуждает задачу, связанную с этим Waker.
Пока исполнитель продолжает работать и задача не завершена, гарантируется, что каждый вызов wake() (или wake_by_ref()) будет сопровождаться как минимум одним вызовом poll() задачи, к которой принадлежит этот Waker. Это позволяет временно уступать другим задачам во время выполнения потенциально неограниченных циклов обработки.
Примечание: вышесказанное подразумевает, что множественные пробуждения могут быть объединены в один вызов poll() средой выполнения.
Также учтите, что уступка конкурирующим задачам не гарантируется: исполнитель сам выбирает, какую задачу запускать, и может выбрать повторный запуск текущей задачи.
wake_by_ref
#![allow(unused)] fn main() { pub fn wake_by_ref(&self) }
Пробуждает задачу, связанную с этим Waker, не потребляя Waker.
Это похоже на wake(), но может быть немного менее эффективно в случае, когда доступен owned Waker. Этот метод следует предпочитать вызову waker.clone().wake().
will_wake
#![allow(unused)] fn main() { pub fn will_wake(&self, other: &Waker) -> bool }
Возвращает true, если этот Waker и другой Waker пробуждают одну и ту же задачу.
Эта функция работает по принципу "best-effort" и может возвращать false, даже если Waker пробуждают одну и ту же задачу. Однако, если функция возвращает true, гарантируется, что Waker пробуждают одну и ту же задачу.
Эта функция в основном используется для оптимизации — например, реализация clone_from этого типа использует её, чтобы избежать клонирования waker, когда они и так пробуждают одну и ту же задачу.
new ⚠️
#![allow(unused)] fn main() { pub const unsafe fn new( data: *const (), vtable: &'static RawWakerVTable, ) -> Waker }
Создает новый Waker из предоставленного указателя данных и vtable.
Доступность: 1.83.0 (const: 1.83.0)
Безопасность
Поведение возвращаемого Waker не определено, если контракт, определенный в документации RawWakerVTable, не соблюдается.
from_raw ⚠️
#![allow(unused)] fn main() { pub const unsafe fn from_raw(waker: RawWaker) -> Waker }
Создает новый Waker из RawWaker.
Доступность: 1.36.0 (const: 1.82.0)
Безопасность
Поведение возвращаемого Waker не определено, если контракт, определенный в документации RawWaker и RawWakerVTable, не соблюдается.
noop
#![allow(unused)] fn main() { pub const fn noop() -> &'static Waker }
Возвращает ссылку на Waker, который ничего не делает при использовании.
Доступность: 1.85.0 (const: 1.85.0)
В основном полезно для написания тестов, которым нужен Context для опроса некоторых future, но которые не ожидают, что эти future пробудят waker, или не нужно делать ничего специфического, если это произойдет.
В более общем смысле, использование Waker::noop() для опроса future означает отбрасывание уведомления о том, когда future следует опросить снова. Поэтому это следует использовать только тогда, когда такое уведомление не потребуется для прогресса.
Если нужен owned Waker, можно клонировать этот.
Примеры
#![allow(unused)] fn main() { use std::future::Future; use std::task; let mut cx = task::Context::from_waker(task::Waker::noop()); let mut future = Box::pin(async { 10 }); assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10)); }
data
#![allow(unused)] fn main() { pub fn data(&self) -> *const () }
Получает указатель данных, использованный для создания этого Waker.
Доступность: 1.83.0
vtable
#![allow(unused)] fn main() { pub fn vtable(&self) -> &'static RawWakerVTable }
Получает указатель vtable, использованный для создания этого Waker.
Доступность: 1.83.0
from_fn_ptr ⚡️
#![allow(unused)] fn main() { pub const fn from_fn_ptr(f: fn()) -> Waker }
Создает Waker из указателя на функцию.
Примечание: Это экспериментальное API, доступно только в ночных сборках Rust.
Реализации трейтов
From<Arc<W>> для Waker
#![allow(unused)] fn main() { impl<W> From<Arc<W>> for Waker where W: Wake + Send + Sync + 'static, }
Использует пробуждаемый тип как Waker.
Особенности:
- Не требует выделения памяти или атомарных операций
- Доступно только на платформах с
target_has_atomic=ptr
Clone
#![allow(unused)] fn main() { impl Clone for Waker }
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &Waker) }
Присваивает клон source для self, если только self.will_wake(source) и так не возвращает true.
Этот метод предпочтительнее простого присваивания source.clone() для self, так как он избегает клонирования waker, если self уже является тем же waker.
Примеры
#![allow(unused)] fn main() { use std::future::Future; use std::pin::Pin; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Waker}; struct Waiter { shared: Arc<Mutex<Shared>>, } struct Shared { waker: Waker, // ... } impl Future for Waiter { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { let mut shared = self.shared.lock().unwrap(); // обновляем waker shared.waker.clone_from(cx.waker()); // логика готовности ... } } }
Debug
#![allow(unused)] fn main() { impl Debug for Waker }
Позволяет форматирование Waker для отладки.
Drop
#![allow(unused)] fn main() { impl Drop for Waker }
Реализует деструктор для Waker.
Автоматические реализации трейтов
Freeze for Waker- может быть замороженRefUnwindSafe for Waker- безопасен для паникиUnwindSafe for Waker- безопасен для паникиSend for Waker- может быть передан между потокамиSync for Waker- может быть разделен между потокамиUnpin for Waker- может быть безопасно перемещено
Назначение
Waker используется для:
- Пробуждения асинхронных задач
- Интеграции с системными событиями
- Создания эффективных исполнителей
- Реализации сложных асинхронных паттернов
Структура ContextBuilder<'a>
Описание
⚡️ Это экспериментальное API, доступно только в ночных сборках Rust.
ContextBuilder - это строитель, используемый для создания экземпляра Context с поддержкой LocalWaker.
Синтаксис
#![allow(unused)] fn main() { pub struct ContextBuilder<'a> { /* приватные поля */ } }
Методы
from_waker ⚡️
#![allow(unused)] fn main() { pub const fn from_waker(waker: &'a Waker) -> ContextBuilder<'a> }
Создает ContextBuilder из Waker.
from ⚡️
#![allow(unused)] fn main() { pub const fn from(cx: &'a mut Context<'_>) -> ContextBuilder<'a> }
Создает ContextBuilder из существующего Context.
waker ⚡️
#![allow(unused)] fn main() { pub const fn waker(self, waker: &'a Waker) -> ContextBuilder<'a> }
Устанавливает значение для waker в Context.
local_waker ⚡️
#![allow(unused)] fn main() { pub const fn local_waker( self, local_waker: &'a LocalWaker, ) -> ContextBuilder<'a> }
Устанавливает значение для local_waker в Context.
ext ⚡️
#![allow(unused)] fn main() { pub const fn ext(self, data: &'a mut (dyn Any + 'static)) -> ContextBuilder<'a> }
Устанавливает значение для данных расширения в Context.
build ⚡️
#![allow(unused)] fn main() { pub const fn build(self) -> Context<'a> }
Собирает Context.
Примеры
#![allow(unused)] #![feature(local_waker)] fn main() { use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; use std::future::Future; let local_waker = LocalWaker::noop(); let waker = Waker::noop(); let mut cx = ContextBuilder::from_waker(&waker) .local_waker(&local_waker) .build(); let mut future = std::pin::pin!(async { 20 }); let poll = future.as_mut().poll(&mut cx); assert_eq!(poll, Poll::Ready(20)); }
Реализации трейтов
Debug
#![allow(unused)] fn main() { impl<'a> Debug for ContextBuilder<'a> }
Позволяет форматирование ContextBuilder для отладки.
Автоматические реализации трейтов
Freeze for ContextBuilder<'a>- может быть заморожен!RefUnwindSafe for ContextBuilder<'a>- не безопасен для паники по ссылке!Send for ContextBuilder<'a>- не может быть передан между потоками!Sync for ContextBuilder<'a>- не может быть разделен между потокамиUnpin for ContextBuilder<'a>- может быть безопасно перемещено!UnwindSafe for ContextBuilder<'a>- не безопасен для паники
Назначение
ContextBuilder используется для:
- Гибкого создания
Contextс различными компонентами - Настройки
LocalWakerиWakerнезависимо друг от друга - Добавления данных расширения в контекст
- Создания специализированных контекстов для тестирования
Особенности
- ⚡️ Все методы помечены как экспериментальные
- Использует fluent interface для цепочки вызовов
- Позволяет тонкую настройку компонентов
Context - Полезен для advanced сценариев работы с асинхронностью
Примечания
- Требует включения фич
local_wakerи/илиcontext_ext - Основное применение - тестирование и кастомные исполнители
- Предоставляет более гибкую альтернативу прямому созданию
Context
Структура LocalWaker
Описание
⚡️ Это экспериментальное API, доступно только в ночных сборках Rust.
LocalWaker аналогичен Waker, но не реализует Send или Sync.
Этот дескриптор инкапсулирует экземпляр RawWaker, который определяет специфичное для исполнителя поведение пробуждения.
Локальные waker могут быть запрошены из Context с помощью метода local_waker.
Типичный жизненный цикл LocalWaker:
- Создается исполнителем
- Оборачивается в
Contextс помощьюContextBuilder - Передается в
Future::poll() - Если future возвращает
Poll::Pending, он должен сохранить waker и вызватьLocalWaker::wake(), когда future нужно опросить снова
Реализует Clone, но не Send или Sync; следовательно, локальный waker не может быть перемещен в другие потоки. В общем случае, при выборе между waker и локальными waker, локальные waker предпочтительнее, если только waker не нужно отправлять между потоками. Это связано с тем, что waker могут нести дополнительные затраты, связанные с синхронизацией памяти.
Примечание: предпочтительнее использовать local_waker.clone_from(&new_waker) вместо *local_waker = new_waker.clone(), так как первый вариант избежит ненужного клонирования waker, если оба waker пробуждают одну и ту же задачу.
Синтаксис
#![allow(unused)] fn main() { pub struct LocalWaker { /* приватные поля */ } }
Методы
wake ⚡️
#![allow(unused)] fn main() { pub fn wake(self) }
Пробуждает задачу, связанную с этим LocalWaker.
Пока исполнитель продолжает работать и задача не завершена, гарантируется, что каждый вызов wake() (или wake_by_ref()) будет сопровождаться как минимум одним вызовом poll() задачи, к которой принадлежит этот LocalWaker. Это позволяет временно уступать другим задачам во время выполнения потенциально неограниченных циклов обработки.
Примечание: вышесказанное подразумевает, что множественные пробуждения могут быть объединены в один вызов poll() средой выполнения.
Также учтите, что уступка конкурирующим задачам не гарантируется: исполнитель сам выбирает, какую задачу запускать, и может выбрать повторный запуск текущей задачи.
wake_by_ref ⚡️
#![allow(unused)] fn main() { pub fn wake_by_ref(&self) }
Пробуждает задачу, связанную с этим LocalWaker, не потребляя LocalWaker.
Это похоже на wake(), но может быть немного менее эффективно в случае, когда доступен owned Waker. Этот метод следует предпочитать вызову waker.clone().wake().
will_wake ⚡️
#![allow(unused)] fn main() { pub fn will_wake(&self, other: &LocalWaker) -> bool }
Возвращает true, если этот LocalWaker и другой LocalWaker пробуждают одну и ту же задачу.
Эта функция работает по принципу "best-effort" и может возвращать false, даже если Waker пробуждают одну и ту же задачу. Однако, если функция возвращает true, гарантируется, что Waker пробуждают одну и ту же задачу.
Эта функция в основном используется для оптимизации — например, реализация clone_from этого типа использует её, чтобы избежать клонирования waker, когда они и так пробуждают одну и ту же задачу.
new ⚡️ ⚠️
#![allow(unused)] fn main() { pub const unsafe fn new( data: *const (), vtable: &'static RawWakerVTable, ) -> LocalWaker }
Создает новый LocalWaker из предоставленного указателя данных и vtable.
Указатель данных может использоваться для хранения произвольных данных, требуемых исполнителем. Это может быть, например, type-erased указатель на Arc, связанный с задачей. Значение этого указателя будет передаваться всем функциям, которые являются частью vtable, в качестве первого параметра.
Vtable настраивает поведение LocalWaker. Для каждой операции на LocalWaker будет вызываться связанная функция в vtable.
Безопасность
Поведение возвращаемого Waker не определено, если контракт, определенный в документации RawWakerVTable, не соблюдается.
from_raw ⚡️ ⚠️
#![allow(unused)] fn main() { pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker }
Создает новый LocalWaker из RawWaker.
Поведение возвращаемого LocalWaker не определено, если контракт, определенный в документации RawWaker и RawWakerVTable, не соблюдается. Поэтому этот метод небезопасен.
noop ⚡️
#![allow(unused)] fn main() { pub const fn noop() -> &'static LocalWaker }
Возвращает ссылку на LocalWaker, который ничего не делает при использовании.
В основном полезно для написания тестов, которым нужен Context для опроса некоторых future, но которые не ожидают, что эти future пробудят waker, или не нужно делать ничего специфического, если это произойдет.
В более общем смысле, использование LocalWaker::noop() для опроса future означает отбрасывание уведомления о том, когда future следует опросить снова. Поэтому это следует использовать только тогда, когда такое уведомление не потребуется для прогресса.
Если нужен owned LocalWaker, можно клонировать этот.
Примеры
#![allow(unused)] #![feature(local_waker)] fn main() { use std::future::Future; use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; let mut cx = ContextBuilder::from_waker(Waker::noop()) .local_waker(LocalWaker::noop()) .build(); let mut future = Box::pin(async { 10 }); assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(10)); }
data ⚡️
#![allow(unused)] fn main() { pub fn data(&self) -> *const () }
Получает указатель данных, использованный для создания этого LocalWaker.
vtable ⚡️
#![allow(unused)] fn main() { pub fn vtable(&self) -> &'static RawWakerVTable }
Получает указатель vtable, использованный для создания этого LocalWaker.
from_fn_ptr ⚡️
#![allow(unused)] fn main() { pub const fn from_fn_ptr(f: fn()) -> LocalWaker }
Создает LocalWaker из указателя на функцию.
Примеры
Использование локального waker для реализации future, аналогичного std::thread::yield_now().
#![allow(unused)] #![feature(local_waker)] fn main() { use std::future::{Future, poll_fn}; use std::task::Poll; // future, который возвращает Pending один раз fn yield_now() -> impl Future<Output=()> + Unpin { let mut yielded = false; poll_fn(move |cx| { if !yielded { yielded = true; cx.local_waker().wake_by_ref(); return Poll::Pending; } return Poll::Ready(()) }) } yield_now().await; }
Реализации трейтов
From<Rc<W>> для LocalWaker
#![allow(unused)] fn main() { impl<W> From<Rc<W>> for LocalWaker where W: LocalWake + 'static, }
Использует пробуждаемый тип как LocalWaker.
Особенности:
- Не требует выделения памяти или атомарных операций
- Работает с типами, не реализующими
Send + Sync
Clone
#![allow(unused)] fn main() { impl Clone for LocalWaker }
clone_from
#![allow(unused)] fn main() { fn clone_from(&mut self, source: &LocalWaker) }
Выполняет копирующее присваивание из source.
Debug
#![allow(unused)] fn main() { impl Debug for LocalWaker }
Позволяет форматирование LocalWaker для отладки.
Drop
#![allow(unused)] fn main() { impl Drop for LocalWaker }
Реализует деструктор для LocalWaker.
Автоматические реализации трейтов
Freeze for LocalWaker- может быть замороженRefUnwindSafe for LocalWaker- безопасен для паникиUnwindSafe for LocalWaker- безопасен для паники!Send for LocalWaker- не может быть передан между потоками!Sync for LocalWaker- не может быть разделен между потокамиUnpin for LocalWaker- может быть безопасно перемещено
Назначение
LocalWaker используется для:
- Оптимизации производительности в однопоточных сценариях
- Избежания накладных расходов на синхронизацию памяти
- Создания более эффективных исполнителей задач
- Специализированных асинхронных примитивов
Преимущества
- Меньшие накладные расходы по сравнению с
Waker - Не требует атомарных операций для подсчета ссылок
- Подходит для однопоточных исполнителей
Enum
Перечисление Poll<T>
Описание
Указывает, доступно ли значение или текущая задача была запланирована для получения пробуждения.
Возвращается методом Future::poll.
Варианты
Ready(T)
Доступность: 1.36.0
Представляет, что значение готово немедленно.
Pending
Доступность: 1.36.0
Представляет, что значение еще не готово.
Когда функция возвращает Pending, она также должна обеспечить, что текущая задача будет запланирована для пробуждения, когда можно будет сделать прогресс.
Методы
map
#![allow(unused)] fn main() { pub fn map<U, F>(self, f: F) -> Poll<U> where F: FnOnce(T) -> U, }
Преобразует Poll<T> в Poll<U>, применяя функцию к содержащемуся значению.
Доступность: 1.36.0
Примеры
Преобразует Poll<String> в Poll<usize>, потребляя оригинал:
#![allow(unused)] fn main() { let poll_some_string = Poll::Ready(String::from("Hello, World!")); // `Poll::map` принимает self *по значению*, потребляя `poll_some_string` let poll_some_len = poll_some_string.map(|s| s.len()); assert_eq!(poll_some_len, Poll::Ready(13)); }
is_ready
#![allow(unused)] fn main() { pub const fn is_ready(&self) -> bool }
Возвращает true, если опрос является значением Poll::Ready.
Доступность: 1.36.0 (const: 1.49.0)
Примеры
#![allow(unused)] fn main() { let x: Poll<u32> = Poll::Ready(2); assert_eq!(x.is_ready(), true); let x: Poll<u32> = Poll::Pending; assert_eq!(x.is_ready(), false); }
is_pending
#![allow(unused)] fn main() { pub const fn is_pending(&self) -> bool }
Возвращает true, если опрос является значением Pending.
Доступность: 1.36.0 (const: 1.49.0)
Примеры
#![allow(unused)] fn main() { let x: Poll<u32> = Poll::Ready(2); assert_eq!(x.is_pending(), false); let x: Poll<u32> = Poll::Pending; assert_eq!(x.is_pending(), true); }
Методы для Poll<Result<T, E>>
map_ok
#![allow(unused)] fn main() { pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>> where F: FnOnce(T) -> U, }
Преобразует Poll<Result<T, E>> в Poll<Result<U, E>>, применяя функцию к содержащемуся значению Poll::Ready(Ok), оставляя все другие варианты нетронутыми.
Доступность: 1.36.0
Примеры
#![allow(unused)] fn main() { let res: Poll<Result<u8, _>> = Poll::Ready("12".parse()); let squared = res.map_ok(|n| n * n); assert_eq!(squared, Poll::Ready(Ok(144))); }
map_err
#![allow(unused)] fn main() { pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>> where F: FnOnce(E) -> U, }
Преобразует Poll::Ready<Result<T, E>> в Poll::Ready<Result<T, U>>, применяя функцию к содержащемуся значению Poll::Ready(Err), оставляя все другие варианты нетронутыми.
Доступность: 1.36.0
Примеры
#![allow(unused)] fn main() { let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse()); let res = res.map_err(|_| 0_u8); assert_eq!(res, Poll::Ready(Err(0))); }
Методы для Poll<Option<Result<T, E>>>
map_ok
#![allow(unused)] fn main() { pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> where F: FnOnce(T) -> U, }
Преобразует Poll<Option<Result<T, E>>> в Poll<Option<Result<U, E>>>, применяя функцию к содержащемуся значению Poll::Ready(Some(Ok)), оставляя все другие варианты нетронутыми.
Доступность: 1.51.0
Примеры
#![allow(unused)] fn main() { let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse())); let squared = res.map_ok(|n| n * n); assert_eq!(squared, Poll::Ready(Some(Ok(144)))); }
map_err
#![allow(unused)] fn main() { pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> where F: FnOnce(E) -> U, }
Преобразует Poll::Ready<Option<Result<T, E>>> в Poll::Ready<Option<Result<T, F>>>, применяя функцию к содержащемуся значению Poll::Ready(Some(Err)), оставляя все другие варианты нетронутыми.
Доступность: 1.51.0
Примеры
#![allow(unused)] fn main() { let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse())); let res = res.map_err(|_| 0_u8); assert_eq!(res, Poll::Ready(Some(Err(0)))); }
Реализации трейтов
From<T> для Poll<T>
#![allow(unused)] fn main() { impl<T> From<T> for Poll<T> }
Перемещает значение в Poll::Ready, чтобы создать Poll<T>.
Пример
#![allow(unused)] fn main() { assert_eq!(Poll::from(true), Poll::Ready(true)); }
Clone
#![allow(unused)] fn main() { impl<T> Clone for Poll<T> where T: Clone }
Позволяет клонирование Poll<T>.
Debug
#![allow(unused)] fn main() { impl<T> Debug for Poll<T> where T: Debug }
Позволяет форматирование Poll<T> для отладки.
PartialEq и Eq
#![allow(unused)] fn main() { impl<T> PartialEq for Poll<T> where T: PartialEq impl<T> Eq for Poll<T> where T: Eq }
Реализует проверку на равенство для Poll<T>.
PartialOrd и Ord
#![allow(unused)] fn main() { impl<T> PartialOrd for Poll<T> where T: PartialOrd impl<T> Ord for Poll<T> where T: Ord }
Реализует сравнение для Poll<T>.
Hash
#![allow(unused)] fn main() { impl<T> Hash for Poll<T> where T: Hash }
Позволяет хеширование Poll<T>.
Copy
#![allow(unused)] fn main() { impl<T> Copy for Poll<T> where T: Copy }
Позволяет копирование Poll<T> по значению.
Экспериментальные реализации трейтов
Try для Poll<Result<T, E>> ⚡️
#![allow(unused)] fn main() { impl<T, E> Try for Poll<Result<T, E>> }
Экспериментальная реализация трейта Try для композиции операций.
Try для Poll<Option<Result<T, E>>> ⚡️
#![allow(unused)] fn main() { impl<T, E> Try for Poll<Option<Result<T, E>>> }
Экспериментальная реализация трейта Try для вложенных типов.
Автоматические реализации трейтов
Freeze for Poll<T>- может быть заморожен, еслиT: FreezeRefUnwindSafe for Poll<T>- безопасен для паники, еслиT: RefUnwindSafeSend for Poll<T>- может быть передан между потоками, еслиT: SendSync for Poll<T>- может быть разделен между потоками, еслиT: SyncUnpin for Poll<T>- может быть безопасно перемещено, еслиT: UnpinUnwindSafe for Poll<T>- безопасен для паники, еслиT: UnwindSafe
Назначение
Poll<T> используется для:
- Возврата состояния асинхронных операций
- Реализации Future-трейтов
- Управления потоком выполнения в асинхронном коде
- Кооперативной многозадачности
Traits
Трейт Wake
Описание
Доступно только на платформах с target_has_atomic=ptr.
Реализация пробуждения задачи на исполнителе.
Этот трейт может быть использован для создания Waker. Исполнитель может определить реализацию этого трейта и использовать её для создания Waker, который передается задачам, выполняемым на этом исполнителе.
Этот трейт является безопасной с точки зрения памяти и эргономичной альтернативой созданию RawWaker. Он поддерживает распространенный дизайн исполнителей, в котором данные, используемые для пробуждения задачи, хранятся в Arc. Некоторые исполнители (особенно для встроенных систем) не могут использовать этот API, поэтому RawWaker существует как альтернатива для таких систем.
Чтобы создать Waker из некоторого типа W, реализующего этот трейт, оберните его в Arc<W> и вызовите Waker::from() на нем. Также возможно преобразование в RawWaker таким же способом.
Синтаксис
#![allow(unused)] fn main() { pub trait Wake { // Обязательный метод fn wake(self: Arc<Self>); // Предоставляемый метод fn wake_by_ref(self: &Arc<Self>) { ... } } }
Обязательные методы
wake
#![allow(unused)] fn main() { fn wake(self: Arc<Self>) }
Пробудить эту задачу.
Предоставляемые методы
wake_by_ref
#![allow(unused)] fn main() { fn wake_by_ref(self: &Arc<Self>) }
Пробудить эту задачу без потребления waker.
Если исполнитель поддерживает более дешевый способ пробуждения без потребления waker, он должен переопределить этот метод. По умолчанию он клонирует Arc и вызывает wake на клоне.
Примеры
Базовая функция block_on, которая принимает future и выполняет его до завершения на текущем потоке.
Примечание: Этот пример жертвует корректностью ради простоты. Чтобы предотвратить взаимные блокировки, реализации производственного уровня также должны обрабатывать промежуточные вызовы thread::unpark, а также вложенные вызовы.
#![allow(unused)] fn main() { use std::future::Future; use std::sync::Arc; use std::task::{Context, Poll, Wake}; use std::thread::{self, Thread}; use core::pin::pin; /// Waker, который пробуждает текущий поток при вызове. struct ThreadWaker(Thread); impl Wake for ThreadWaker { fn wake(self: Arc<Self>) { self.0.unpark(); } } /// Выполнить future до завершения на текущем потоке. fn block_on<T>(fut: impl Future<Output = T>) -> T { // Закрепляем future, чтобы его можно было опросить. let mut fut = pin!(fut); // Создаем новый контекст для передачи в future. let t = thread::current(); let waker = Arc::new(ThreadWaker(t)).into(); let mut cx = Context::from_waker(&waker); // Выполняем future до завершения. loop { match fut.as_mut().poll(&mut cx) { Poll::Ready(res) => return res, Poll::Pending => thread::park(), } } } block_on(async { println!("Hi from inside a future!"); }); }
Совместимость с dyn
Этот трейт не совместим с dyn.
В старых версиях Rust совместимость с dyn называлась "object safety", поэтому этот трейт не является object safe.
Реализаторы
Автоматические реализации
Трейт Wake автоматически реализуется для:
- Типов, которые уже реализуют
Wake Arc<W>гдеW: Wake
Ручные реализации
Разработчики могут реализовать Wake для своих кастомных типов:
#![allow(unused)] fn main() { use std::sync::Arc; use std::task::Wake; struct MyWaker; impl Wake for MyWaker { fn wake(self: Arc<Self>) { // Кастомная логика пробуждения } // Опционально переопределить wake_by_ref для оптимизации fn wake_by_ref(self: &Arc<Self>) { // Более эффективная реализация без клонирования } } }
Использование с исполнителями
Создание Waker из типа Wake
#![allow(unused)] fn main() { use std::sync::Arc; use std::task::Waker; let my_waker = Arc::new(MyWaker); let waker: Waker = Waker::from(my_waker); }
Интеграция с Context
#![allow(unused)] fn main() { use std::task::Context; let waker = Arc::new(MyWaker).into(); let mut cx = Context::from_waker(&waker); }
Преимущества перед RawWaker
- Безопасность памяти: не требует небезопасного кода
- Эргономичность: простой API с автоматическим управлением памятью
- Интеграция с Arc: естественно работает со счетчиком ссылок
- Оптимизация: возможность переопределить
wake_by_ref
Ограничения
- Требует выделения памяти в куче для
Arc - Доступен только на платформах с атомарными указателями
- Не подходит для no_std сред без аллокатора
Рекомендации по использованию
- Используйте
Wakeдля большинства исполнителей - Переопределяйте
wake_by_refдля оптимизации производительности - Используйте
RawWakerтолько когдаWakeнедоступен - Обеспечьте корректную синхронизацию для многопоточных исполнителей
Трейт LocalWake
Описание
⚡️ Это экспериментальное API, доступно только в ночных сборках Rust.
Аналогичный трейт Wake, но используемый для создания LocalWaker.
Этот API работает точно так же, как Wake, за исключением того, что он использует Rc вместо Arc, и результатом является LocalWaker вместо Waker.
Преимущества использования LocalWaker вместо Waker заключаются в том, что он позволяет локальному waker хранить данные, которые не реализуют Send и Sync. Дополнительно, это экономит вызовы Arc::clone, которые требуют атомарной синхронизации.
Синтаксис
#![allow(unused)] fn main() { pub trait LocalWake { // Обязательный метод fn wake(self: Rc<Self>); // Предоставляемый метод fn wake_by_ref(self: &Rc<Self>) { ... } } }
Обязательные методы
wake ⚡️
#![allow(unused)] fn main() { fn wake(self: Rc<Self>) }
Пробудить эту задачу.
Предоставляемые методы
wake_by_ref ⚡️
#![allow(unused)] fn main() { fn wake_by_ref(self: &Rc<Self>) }
Пробудить эту задачу без потребления локального waker.
Если исполнитель поддерживает более дешевый способ пробуждения без потребления waker, он должен переопределить этот метод. По умолчанию он клонирует Rc и вызывает wake на клоне.
Примеры
Это упрощенный пример функций spawn и block_on. Функция spawn используется для добавления новых задач в очередь выполнения, а функция block_on будет удалять их и опрашивать. Когда задача пробуждается, она помещает себя обратно в очередь выполнения для опроса исполнителем.
Примечание: Этот пример жертвует корректностью ради простоты. Реальный пример будет чередовать вызовы poll с вызовами io реактора для ожидания событий вместо циклического опроса.
#![allow(unused)] #![feature(local_waker)] fn main() { use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker}; use std::future::Future; use std::pin::Pin; use std::rc::Rc; use std::cell::RefCell; use std::collections::VecDeque; thread_local! { // Очередь, содержащая все задачи, готовые к выполнению static RUN_QUEUE: RefCell<VecDeque<Rc<Task>>> = RefCell::default(); } type BoxedFuture = Pin<Box<dyn Future<Output = ()>>>; struct Task(RefCell<BoxedFuture>); impl LocalWake for Task { fn wake(self: Rc<Self>) { RUN_QUEUE.with_borrow_mut(|queue| { queue.push_back(self) }) } } fn spawn<F>(future: F) where F: Future<Output=()> + 'static + Send + Sync { let task = RefCell::new(Box::pin(future)); RUN_QUEUE.with_borrow_mut(|queue| { queue.push_back(Rc::new(Task(task))); }); } fn block_on<F>(future: F) where F: Future<Output=()> + 'static + Sync + Send { spawn(future); loop { let Some(task) = RUN_QUEUE.with_borrow_mut(|queue| queue.pop_front()) else { // выходим, так как в очереди больше нет задач return; }; // преобразуем Rc<Task> в `LocalWaker` let local_waker: LocalWaker = task.clone().into(); // Строим контекст с помощью `ContextBuilder` let mut cx = ContextBuilder::from_waker(Waker::noop()) .local_waker(&local_waker) .build(); // Опрашиваем задачу let _ = task.0 .borrow_mut() .as_mut() .poll(&mut cx); } } block_on(async { println!("hello world"); }); }
Совместимость с dyn
Этот трейт не совместим с dyn.
В старых версиях Rust совместимость с dyn называлась "object safety", поэтому этот трейт не является object safe.
Реализаторы
Автоматические реализации
Трейт LocalWake автоматически реализуется для:
- Типов, которые уже реализуют
LocalWake Rc<W>гдеW: LocalWake
Ручные реализации
Разработчики могут реализовать LocalWake для своих кастомных типов:
#![allow(unused)] #![feature(local_waker)] fn main() { use std::rc::Rc; use std::task::LocalWake; struct MyLocalWaker; impl LocalWake for MyLocalWaker { fn wake(self: Rc<Self>) { // Кастомная логика пробуждения } // Опционально переопределить wake_by_ref для оптимизации fn wake_by_ref(self: &Rc<Self>) { // Более эффективная реализация без клонирования } } }
Использование с исполнителями
Создание LocalWaker из типа LocalWake
#![allow(unused)] #![feature(local_waker)] fn main() { use std::rc::Rc; use std::task::LocalWaker; let my_local_waker = Rc::new(MyLocalWaker); let local_waker: LocalWaker = LocalWaker::from(my_local_waker); }
Интеграция с Context
#![allow(unused)] #![feature(local_waker)] fn main() { use std::task::{ContextBuilder, Waker}; let local_waker = Rc::new(MyLocalWaker).into(); let mut cx = ContextBuilder::from_waker(Waker::noop()) .local_waker(&local_waker) .build(); }
Преимущества перед Wake
- Отсутствие атомарных операций: использует
RcвместоArc - Поддержка !Send/!Sync типов: может хранить не-потокобезопасные данные
- Производительность: избегает накладных расходов атомарного подсчета ссылок
- Гибкость: подходит для однопоточных исполнителей
Ограничения
- ⚡️ Доступен только в ночных сборках Rust
- Не может быть использован в многопоточных сценариях
- Требует включения фичи
local_waker
Сравнение с Wake
| Характеристика | Wake | LocalWake |
|---|---|---|
| Тип указателя | Arc | Rc |
| Потокобезопасность | Send + Sync | !Send + !Sync |
| Атомарные операции | Да | Нет |
| Производительность | Ниже | Выше |
| Применение | Многопоточное | Однопоточное |
Рекомендации по использованию
- Используйте
LocalWakeдля однопоточных исполнителей - Переопределяйте
wake_by_refдля избежания клонированияRc - Комбинируйте с
ContextBuilderдля гибкого создания контекста - Используйте для оптимизации производительности в single-threaded средах
Ключевые слова
note
Ключевые слова в Rust — это зарезервированные идентификаторы, которые имеют специальное значение в языке и не могут использоваться как имена переменных, функций, модулей и других сущностей.
Основные категории ключевых слов:
🏗️ Объявление сущностей
fn- функцииlet- переменныеstruct,enum,union- составные типыmod- модулиtrait- трейтыimpl- реализации
🔒 Управление видимостью
pub- публичная видимостьuse- импорт
📦 Типы и дженерики
type- псевдонимы типовwhere- ограничения дженериковdyn- динамическая диспетчеризация трейтов
⚡ Управление памятью
move- перенос владенияref- заимствование по ссылкеmut- изменяемость
🔄 Поток управления
if,else,match- условные конструкцииloop,while,for- циклыbreak,continue- управление цикламиreturn- возврат из функций
🛡️ Безопасность и обработка ошибок
unsafe- небезопасный кодasync,await- асинхронное программирование
🎯 Специальные типы
self,Self- текущий экземпляр/типtrue,false- булевы значенияNone,Some- варианты Option
Особенности:
- ✅ Зарезервированы - нельзя использовать как имена
- ✅ Строгие правила применения
- ✅ Контекстно-зависимые - некоторые имеют разное значение в разных контекстах
Ключевое слово as
Приведение между типами
Ключевое слово as чаще всего используется для преобразования примитивных типов в другие примитивные типы, но также имеет и другие применения, включая преобразование указателей в адреса, адресов в указатели и указателей в другие указатели.
#![allow(unused)] fn main() { let thing1: u8 = 89.0 as u8; assert_eq!('B' as u32, 66); assert_eq!(thing1 as char, 'Y'); let thing2: f32 = thing1 as f32 + 10.5; assert_eq!(true as u8 + thing2 as u8, 100); }
В общем случае, любое приведение, которое может быть выполнено через указание типа, также может быть сделано с помощью as. Таким образом, вместо написания let x: u32 = 123 можно написать let x = 123 as u32 (примечание: в этой ситуации лучше использовать let x: u32 = 123). Однако обратное неверно; явное использование as позволяет несколько больше приведений, которые не разрешены неявно, таких как изменение типа сырого указателя или преобразование замыканий в сырые указатели.
as можно рассматривать как примитивный аналог From и Into: as работает только с примитивами (u8, bool, str, указатели, …), тогда как From и Into также работают с типами вроде String или Vec.
as также может использоваться с заполнителем _, когда целевой тип может быть выведен. Обратите внимание, что это может нарушить вывод типов, и обычно в таком коде следует использовать явный тип для ясности и стабильности. Это наиболее полезно при преобразовании указателей с помощью as *const _ или as *mut _, хотя метод cast рекомендуется вместо as *const _, и то же самое для as *mut _: эти методы делают намерение более понятным.
Переименование импортов
as также используется для переименования импортов в операторах use и extern crate:
#![allow(unused)] fn main() { use std::{mem as memory, net as network}; // Теперь можно использовать имена `memory` и `network` для ссылки на `std::mem` и `std::net`. }
Квалификация путей
С From и Into, как и со всеми трейтами, as используется для полностью квалифицированного пути — средства устранения неоднозначности связанных элементов, то есть функций, констант и типов. Например, если у вас есть тип, который реализует два трейта с одинаковыми именами методов (например, Into::<u32>::into и Into::<u64>::into), вы можете уточнить, какой метод использовать с помощью <MyThing as Into<u32>>::into(my_thing)¹. Это довольно многословно, но, к счастью, вывод типов в Rust обычно избавляет от необходимости в этом, хотя иногда это необходимо, особенно с методами, которые возвращают обобщённый тип, такие как Into::into, или методы, которые не принимают self. Это более распространено в макросах, где это может обеспечить необходимую гигиену.
Дальнейшее чтение
Для получения дополнительной информации о возможностях as см. Справочник по:
- выражениям приведения типов,
- переименованию импортированных сущностей,
- переименованию внешних крейтов,
- квалифицированным путям.
¹ Вероятно, вам никогда не следует использовать этот синтаксис с Into, а вместо этого писать T::from(my_thing). Просто так сложилось, что в стандартной библиотеке нет хороших примеров для этого синтаксиса. Также на момент написания компилятор обычно предлагает полностью квалифицированные пути для исправления неоднозначных вызовов Into::into, так что пример должен быть знаком.
Ключевое слово as в Rust: основные способы применения
1. Приведение числовых типов
fn main() { // Целочисленные преобразования let x: i32 = 42; let y: u64 = x as u64; println!("i32 {} -> u64 {}", x, y); // С плавающей точкой let float_num: f64 = 3.14; let int_num: i32 = float_num as i32; // Дробная часть отбрасывается println!("f64 {} -> i32 {}", float_num, int_num); // Беззнаковые в знаковые let unsigned: u8 = 200; let signed: i8 = unsigned as i8; // Может привести к переполнению println!("u8 {} -> i8 {}", unsigned, signed); // Между целыми разного размера let large: i128 = 1000; let small: i8 = large as i8; // Обрезание битов println!("i128 {} -> i8 {}", large, small); }
2. Преобразования с плавающей точкой
fn main() { // Float <-> Integer let pi: f32 = 3.14159; let pi_int = pi as i32; println!("f32 {} -> i32 {}", pi, pi_int); // 3 // Обратное преобразование let count: i32 = 42; let count_float = count as f64; println!("i32 {} -> f64 {}", count, count_float); // Между float типами let float32: f32 = 2.5; let float64: f64 = float32 as f64; println!("f32 {} -> f64 {}", float32, float64); }
3. Работа с указателями
fn main() { let x = 42; // Создание сырых указателей let raw_ptr: *const i32 = &x as *const i32; println!("Raw pointer: {:?}", raw_ptr); // Преобразование между типами указателей let mut y = 100; let const_ptr: *const i32 = &y as *const i32; let mut_ptr: *mut i32 = &mut y as *mut i32; // Преобразование указателей разных типов let byte_ptr = const_ptr as *const u8; println!("i32 pointer: {:?} -> u8 pointer: {:?}", const_ptr, byte_ptr); // Приведение к usize для арифметики указателей let addr = const_ptr as usize; println!("Pointer as usize: 0x{:x}", addr); }
4. Преобразования с enum
fn main() { // Enum без данных -> целые числа enum Color { Red = 0xff0000, Green = 0x00ff00, Blue = 0x0000ff, } let color_value = Color::Red as i32; println!("Color Red as i32: 0x{:x}", color_value); // C-like enums #[repr(u8)] enum Status { Ok = 0, Error = 1, Loading = 2, } let status_code = Status::Error as u8; println!("Status code: {}", status_code); // Bool -> integer let true_as_int = true as i32; // 1 let false_as_int = false as i32; // 0 println!("true as i32: {}, false as i32: {}", true_as_int, false_as_int); }
5. Работа с массивами и срезами
fn main() { // Приведение ссылок на массивы let arr: [i32; 4] = [1, 2, 3, 4]; let slice: &[i32] = &arr as &[i32]; println!("Array as slice: {:?}", slice); // Байтовые представления let value: u32 = 0x12345678; let bytes: &[u8] = unsafe { std::slice::from_raw_parts( &value as *const u32 as *const u8, std::mem::size_of::<u32>() ) }; println!("u32 0x{:x} as bytes: {:?}", value, bytes); // Приведение размеров срезов (осторожно!) let int_slice: &[i32] = &[1, 2, 3, 4]; let byte_slice: &[u8] = unsafe { std::slice::from_raw_parts( int_slice.as_ptr() as *const u8, int_slice.len() * std::mem::size_of::<i32>() ) }; println!("i32 slice as u8 slice: {:?}", byte_slice); }
6. Преобразования в трейт-объекты
trait Animal { fn speak(&self); } struct Dog; struct Cat; impl Animal for Dog { fn speak(&self) { println!("Woof!"); } } impl Animal for Cat { fn speak(&self) { println!("Meow!"); } } fn main() { let dog = Dog; let cat = Cat; // Создание трейт-объектов let animal1: &dyn Animal = &dog as &dyn Animal; let animal2: &dyn Animal = &cat as &dyn Animal; animal1.speak(); animal2.speak(); // Boxed trait objects let boxed_animal: Box<dyn Animal> = Box::new(Dog) as Box<dyn Animal>; boxed_animal.speak(); }
7. Явное приведение типов в выражениях
fn main() { // Для разрешения неоднозначности let result1 = 10 as f64 / 3.0; let result2 = 10 / 3 as f64; println!("10 as f64 / 3.0 = {}", result1); // 3.333... println!("10 / 3 as f64 = {}", result2); // 3.0 // В арифметических операциях let a: u8 = 100; let b: u8 = 200; let sum = a as u16 + b as u16; // Предотвращаем переполнение println!("{} + {} = {} (as u16)", a, b, sum); // При работе с индексами let arr = [10, 20, 30, 40]; let index: i32 = 2; let element = arr[index as usize]; // Приведение для индексации println!("arr[{}] = {}", index, element); }
8. Преобразования с char
fn main() { // Char <-> числовые типы let letter = 'A'; let letter_code = letter as u8; println!("'{}' as u8: {}", letter, letter_code); let number = 66u8; let character = number as char; println!("{} as char: '{}'", number, character); // Unicode символы let heart = '💖'; let heart_code = heart as u32; println!("'{}' as u32: 0x{:x}", heart, heart_code); // Осторожно: не все числовые значения - валидные char let invalid_char = 0xD800 as char; // Это surrogate pair, не валидный char! println!("Invalid char: {:?}", invalid_char); // Может привести к неопределенному поведению }
9. Приведение в замыканиях и функциях
fn main() { // Приведение типов функций fn normal_function(x: i32) -> i32 { x * 2 } let function_ptr: fn(i32) -> i32 = normal_function as fn(i32) -> i32; println!("Function result: {}", function_ptr(21)); // Замыкания (требуют осторожности) let closure = |x: i32| x + 1; let closure_ptr: fn(i32) -> i32 = closure as fn(i32) -> i32; println!("Closure result: {}", closure_ptr(10)); // Приведение к указателям на функции type MathFn = fn(i32, i32) -> i32; fn add(a: i32, b: i32) -> i32 { a + b } fn multiply(a: i32, b: i32) -> i32 { a * b } let operations: [MathFn; 2] = [ add as MathFn, multiply as MathFn, ]; for op in operations.iter() { println!("Operation result: {}", op(5, 3)); } }
10. Ограничения и безопасность
fn main() { // НЕЛЬЗЯ приводить между произвольными типами struct Point { x: i32, y: i32 } // let p = Point { x: 1, y: 2 }; // let invalid = p as String; // Ошибка компиляции! // Осторожно с потерями точности let large: u64 = u64::MAX; let small: u32 = large as u32; // Потеря данных! println!("u64::MAX {} -> u32 {}", large, small); // Приведение с насыщением (альтернатива) let saturated = large.min(u32::MAX as u64) as u32; println!("Saturated conversion: {}", saturated); }
Важные замечания:
asне выполняет проверки - это простое битовое преобразование- Может терять данные при числовых преобразованиях
- Небезопасно для некоторых преобразований указателей
- Альтернативы:
.try_into(),.into()для безопасных преобразований - Для сложных преобразований используйте
std::convert
Используйте as осторожно и только когда понимаете последствия преобразования!
Ключевое слово async
Возвращает Future вместо блокировки текущего потока.
Используйте async перед fn, замыканием или блоком, чтобы превратить помеченный код в Future. Таким образом, код не будет выполняться немедленно, а будет вычисляться только когда возвращенный фьючер будет ожидаться через .await.
Мы написали книгу по асинхронному программированию, детально описывающую async/await и компромиссы по сравнению с использованием потоков.
Управление потоком выполнения
Операторы return и ? внутри async-блоков не вызывают возврат из родительской функции; вместо этого они вызывают возврат значения из Future, возвращенного блоком.
Например, следующая Rust-функция вернет 5, в результате чего x получит тип !:
#![allow(unused)] fn main() { #[expect(unused_variables)] fn example() -> i32 { let x = { return 5; }; } }
В contrast, следующая асинхронная функция присваивает Future<Output = i32> переменной x, и возвращает 5 только когда x ожидается через .await:
#![allow(unused)] fn main() { async fn example() -> i32 { let x = async { return 5; }; x.await } }
Код с использованием ? ведет себя аналогично - он вызывает возврат Result из async-блока без влияния на родительскую функцию.
Обратите внимание, что вы не можете использовать break или continue внутри async-блока для влияния на управление циклом в родительской функции.
Управление потоком выполнения в async-блоках дополнительно документировано в книге по асинхронному программированию.
Издания (Editions)
async является ключевым словом начиная с издания 2018 года.
Оно доступно для использования в стабильном Rust начиная с версии 1.39.
В contrast, следующая асинхронная функция присваивает Future<Output = i32> переменной x, и возвращает 5 только когда x ожидается через .await:
#![allow(unused)] fn main() { async fn example() -> i32 { let x = async { return 5; }; x.await } }
Код с использованием ? ведет себя аналогично - он вызывает возврат Result из async-блока без влияния на родительскую функцию.
Обратите внимание, что вы не можете использовать break или continue внутри async-блока для влияния на управление циклом в родительской функции.
Управление потоком выполнения в async-блоках дополнительно документировано в книге по асинхронному программированию.
Издания (Editions)
async является ключевым словом начиная с издания 2018 года.
Оно доступно для использования в стабильном Rust начиная с версии 1.39.
Ключевое слово await
Приостанавливает выполнение до тех пор, пока результат Future не будет готов.
Ожидание (.await) фьючера приостанавливает выполнение текущей функции до тех пор, пока исполнитель (executor) не выполнит фьючер до завершения.
Прочитайте книгу по асинхронному программированию для получения подробной информации о том, как работают async/await и исполнители.
Издания (Editions)
await является ключевым словом начиная с издания 2018 года.
Оно доступно для использования в стабильном Rust начиная с версии 1.39.
Ключевое слово const
Константы времени компиляции, блоки времени компиляции, вычисляемые во время компиляции функции и сырые указатели.
Константы времени компиляции
Иногда определённое значение используется многократно throughout программе, и его постоянное копирование может стать неудобным. Более того, не всегда возможно или желательно сделать его переменной, которая передаётся в каждую функцию, где оно нужно. В таких случаях ключевое слово const предоставляет удобную альтернативу дублированию кода:
#![allow(unused)] fn main() { const THING: u32 = 0xABAD1DEA; let foo = 123 + THING; }
Константы должны быть явно типизированы; в отличие от let, вы не можете опустить их тип и позволить компилятору вывести его. Любое постоянное значение может быть определено в const, что на практике охватывает большинство вещей, которые разумно иметь в константе (за исключением const fn). Например, вы не можете иметь File как const.
Единственное время жизни, допустимое в константе, — это 'static, которое охватывает все остальные времена жизни в программе на Rust. Например, если вы хотите определить константную строку, это будет выглядеть так:
#![allow(unused)] fn main() { const WORDS: &'static str = "hello rust!"; }
Благодаря элизии времени жизни static, обычно вам не нужно явно использовать 'static:
#![allow(unused)] fn main() { const WORDS: &str = "hello convenience!"; }
Элементы const выглядят очень похоже на элементы static, что вызывает некоторую путаницу в отношении того, что когда следует использовать. Проще говоря, константы встраиваются (inlined) везде, где они используются, что делает их использование идентичным простой замене имени const на его значение. Статические переменные, с другой стороны, указывают на единственное место в памяти, которое используют все обращения. Это означает, что, в отличие от констант, они не могут иметь деструкторы и выступают в качестве единого значения во всей кодовой базе.
Константы, как и статические переменные, всегда должны быть в SCREAMING_SNAKE_CASE.
Для получения более подробной информации о const см. книгу по Rust или Справочник.
Блоки времени компиляции
Ключевое слово const также может использоваться для определения блока кода, который вычисляется во время компиляции. Это полезно для обеспечения завершения определённых вычислений до оптимизаций, а также до времени выполнения. Для получения более подробной информации см. Справочник.
Вычисляемые во время компиляции функции
Другое основное использование ключевого слова const — в const fn. Это помечает функцию как вызываемую в теле элемента const или static и в инициализаторах массивов (обычно называемых "контекстами const"). const fn ограничены в наборе операций, которые они могут выполнять, чтобы гарантировать, что они могут быть вычислены во время компиляции. См. Справочник для получения более подробной информации.
Преобразование fn в const fn не влияет на использование этой функции во время выполнения.
Другие использования const
Ключевое слово const также используется в сырых указателях в сочетании с mut, как видно в *const T и *mut T. Подробнее о const, используемом в сырых указателях, можно прочитать в документации Rust для примитива pointer.
Ключевое слово impl
Реализации функциональности для типа или типа, реализующего некоторую функциональность.
Существует два варианта использования ключевого слова impl:
- Блок
impl— это элемент, используемый для реализации некоторой функциональности для типа. impl Traitв позиции типа может использоваться для обозначения типа, который реализует трейт с именемTrait.
Реализация функциональности для типа
Ключевое слово impl в первую очередь используется для определения реализаций для типов. Внутренние реализации (inherent implementations) являются самостоятельными, в то время как реализации трейтов (trait implementations) используются для реализации трейтов для типов или других трейтов.
Реализация состоит из определений функций и констант. Функция, определённая в блоке impl, может быть самостоятельной (standalone), что означает, что она будет вызываться как Vec::new(). Если функция принимает self, &self или &mut self в качестве первого аргумента, она также может быть вызвана с использованием синтаксиса вызова метода — знакомой возможности для любого объектно-ориентированного программиста — например, vec.len().
Внутренние реализации (Inherent Implementations)
#![allow(unused)] fn main() { struct Example { number: i32, } impl Example { fn boo() { println!("boo! Example::boo() was called!"); } fn answer(&mut self) { self.number += 42; } fn get_number(&self) -> i32 { self.number } } }
Не имеет большого значения, где определена внутренняя реализация; её функциональность находится в области видимости везде, где находится её реализующий тип.
Реализации трейтов (Trait Implementations)
#![allow(unused)] fn main() { struct Example { number: i32, } trait Thingy { fn do_thingy(&self); } impl Thingy for Example { fn do_thingy(&self) { println!("doing a thing! also, number is {}!", self.number); } } }
Не имеет большого значения, где определена реализация трейта; её функциональность может быть внесена в область видимости путём импорта трейта, который она реализует.
Для получения дополнительной информации о реализациях см. книгу по Rust или Справочник.
Обозначение типа, который реализует некоторую функциональность
Другое использование ключевого слова impl — в синтаксисе impl Trait, который можно понимать как «любой (или некоторый) конкретный тип, который реализует Trait». Он может использоваться как тип объявления переменной, в позиции аргумента или в позиции возврата. Один уместный случай использования — работа с замыканиями, которые имеют неназываемые типы.
#![allow(unused)] fn main() { fn thing_returning_closure() -> impl Fn(i32) -> bool { println!("here's a closure for you!"); |x: i32| x % 3 == 0 } }
Для получения дополнительной информации о синтаксисе impl Trait см. книгу по Rust.
Ключевое слово type
Определение псевдонима для существующего типа.
Синтаксис: type Имя = СуществующийТип;
Примеры
type не создаёт новый тип:
#![allow(unused)] fn main() { type Meters = u32; type Kilograms = u32; let m: Meters = 3; let k: Kilograms = 3; assert_eq!(m, k); }
Тип может быть обобщённым (generic):
#![allow(unused)] fn main() { type ArcMutex<T> = Arc<Mutex<T>>; }
В трейтах type используется для объявления ассоциированного типа:
#![allow(unused)] fn main() { trait Iterator { // объявление ассоциированного типа type Item; fn next(&mut self) -> Option<Self::Item>; } struct Once<T>(Option<T>); impl<T> Iterator for Once<T> { // определение ассоциированного типа type Item = T; fn next(&mut self) -> Option<Self::Item> { self.0.take() } } }
Тип может быть обобщённым (generic):
#![allow(unused)] fn main() { type ArcMutex<T> = Arc<Mutex<T>>; }
В трейтах type используется для объявления ассоциированного типа:
#![allow(unused)] fn main() { trait Iterator { // объявление ассоциированного типа type Item; fn next(&mut self) -> Option<Self::Item>; } struct Once<T>(Option<T>); impl<T> Iterator for Once<T> { // определение ассоциированного типа type Item = T; fn next(&mut self) -> Option<Self::Item> { self.0.take() } } }
Ключевое слово static
Статический элемент — это значение, которое действительно в течение всего времени выполнения вашей программы (время жизни 'static).
На первый взгляд, статические элементы кажутся очень похожими на константы: оба содержат значение, оба требуют аннотаций типов и оба могут быть инициализированы только константными функциями и значениями. Однако статические элементы заметно отличаются тем, что представляют собой расположение в памяти. Это означает, что вы можете иметь ссылки на статические элементы и потенциально даже изменять их, делая их по сути глобальными переменными.
Статические элементы не вызывают drop в конце программы.
Существует два типа статических элементов: объявленные с ключевым словом mut и без него.
Статические элементы не могут быть перемещены: ⓘ
#![allow(unused)] fn main() { static VEC: Vec<u32> = vec![]; fn move_vec(v: Vec<u32>) -> Vec<u32> { v } // Эта строка вызывает ошибку move_vec(VEC); }
Простые статические элементы (без mut)
Доступ к неизменяемым статическим элементам считается безопасным, но применяются некоторые ограничения. Наиболее notably, тип статического значения должен реализовывать трейт Sync, что исключает контейнеры с внутренней изменчивостью, такие как RefCell. См. Справочник для получения более подробной информации.
#![allow(unused)] fn main() { static FOO: [i32; 5] = [1, 2, 3, 4, 5]; let r1 = &FOO as *const _; let r2 = &FOO as *const _; // С строго доступным только для чтения статиком ссылки будут иметь тот же адрес assert_eq!(r1, r2); // Статический элемент может использоваться так же, как переменная, во многих случаях println!("{FOO:?}"); }
Изменяемые статические элементы (с mut)
Если статический элемент объявлен с ключевым словом mut, то программе разрешено его изменять. Однако доступ к изменяемым статикам может вызвать неопределённое поведение различными способами, например, из-за гонки данных в многопоточном контексте. Как таковой, весь доступ к изменяемым статикам требует блока unsafe.
Когда это возможно, часто лучше использовать неизменяемый статик с типом внутренней изменчивости, таким как Mutex, OnceLock или атомарный тип.
Несмотря на их небезопасность, изменяемые статики необходимы во многих контекстах: они могут использоваться для представления глобального состояния, разделяемого всей программой, или в блоках extern для привязки к переменным из библиотек C.
В блоке extern:
#![allow(unused)] fn main() { unsafe extern "C" { static mut ERROR_MESSAGE: *mut std::os::raw::c_char; } }
На изменяемые статики, как и на простые статики, распространяются некоторые ограничения. См. Справочник для получения более подробной информации.
Ключевое слово struct
Тип, который состоит из других типов.
Структуры в Rust бывают трёх видов: структуры с именованными полями, кортежные структуры и unit-структуры.
#![allow(unused)] fn main() { struct Regular { field1: f32, field2: String, pub field3: bool } struct Tuple(u32, String); struct Unit; }
Виды структур
Обычные структуры (с именованными полями) используются наиболее часто. Каждое поле, определённое в них, имеет имя и тип, и после определения к нему можно обращаться с помощью синтаксиса example_struct.field. Поля структуры разделяют её изменяемость, поэтому foo.bar = 2; будет допустимо только если foo является изменяемым. Добавление pub к полю делает его видимым для кода в других модулях, а также позволяет напрямую обращаться к нему и изменять его.
Кортежные структуры похожи на обычные структуры, но их поля не имеют имён. Они используются как кортежи, с возможностью деструктуризации через синтаксис let TupleStruct(x, y) = foo;. Для доступа к отдельным переменным используется тот же синтаксис, что и с обычными кортежами, а именно foo.0, foo.1 и т.д., начиная с нуля.
Unit-структуры чаще всего используются как маркеры. Они имеют размер ноль байт, но в отличие от пустых перечислений могут быть созданы, что делает их изоморфными unit-типу (). Unit-структуры полезны, когда вам нужно реализовать трейт для чего-то, но не нужно хранить внутри какие-либо данные.
Создание экземпляров
Структуры могут быть созданы разными способами, все из которых можно комбинировать по необходимости. Наиболее распространённый способ создания новой структуры — через метод-конструктор, такой как new(), но когда он недоступен (или вы пишете сам конструктор), используется синтаксис литералов структур:
#![allow(unused)] fn main() { let example = Foo { field1: 42.0, field2: "blah".to_string(), etc: true, }; }
Непосредственно создать структуру с помощью синтаксиса литералов структур возможно только тогда, когда все её поля видимы для вас.
Существует несколько сокращений для удобства написания конструкторов, наиболее распространённым из которых является сокращённая инициализация полей. Когда существует переменная и поле с одинаковым именем, присваивание может быть упрощено с field: field до просто field. Следующий пример гипотетического конструктора демонстрирует это:
#![allow(unused)] fn main() { struct User { name: String, admin: bool, } impl User { pub fn new(name: String) -> Self { Self { name, admin: false, } } } }
Другое сокращение для создания структур доступно, когда вам нужно создать новую структуру, которая имеет те же значения, что и большая часть предыдущей структуры того же типа, называемое синтаксисом обновления структуры:
#![allow(unused)] fn main() { let updated_thing = Foo { field1: "a new value".to_string(), ..thing }; }
Кортежные структуры создаются так же, как и сами кортежи, за исключением того, что перед ними ставится имя структуры: Foo(123, false, 0.1).
Пустые структуры создаются просто с помощью их имени и больше ничего не требуют: let thing = EmptyStruct;
Соглашения о стиле
Структуры всегда пишутся в UpperCamelCase, за редкими исключениями. Хотя завершающая запятая в списке полей структуры может быть опущена, её обычно оставляют для удобства добавления и удаления полей в будущем.
Для получения дополнительной информации о структурах ознакомьтесь с книгой по Rust или Справочником.
Ключевое слово trait
Общий интерфейс для группы типов.
Трейт похож на интерфейс, который могут реализовывать типы данных. Когда тип реализует трейт, он может рассматриваться абстрактно как этот трейт с использованием обобщений или трейт-объектов.
Трейты могут состоять из трёх видов ассоциированных элементов:
- функции и методы
- типы
- константы
Трейты также могут содержать дополнительные параметры типов. Эти параметры типов или сам трейт могут быть ограничены другими трейтами.
Трейты могут служить маркерами или нести другую логическую семантику, которая не выражается через их элементы. Когда тип реализует такой трейт, он гарантирует соблюдение его контракта. Send и Sync — два таких маркерных трейта, присутствующих в стандартной библиотеке.
См. Справочник для получения дополнительной информации о трейтах.
Примеры
Трейты объявляются с помощью ключевого слова trait. Типы могут реализовывать их с помощью impl Trait for Type:
#![allow(unused)] fn main() { trait Zero { const ZERO: Self; fn is_zero(&self) -> bool; } impl Zero for i32 { const ZERO: Self = 0; fn is_zero(&self) -> bool { *self == Self::ZERO } } assert_eq!(i32::ZERO, 0); assert!(i32::ZERO.is_zero()); assert!(!4.is_zero()); }
С ассоциированным типом:
#![allow(unused)] fn main() { trait Builder { type Built; fn build(&self) -> Self::Built; } }
Трейты могут быть обобщёнными, с ограничениями или без:
#![allow(unused)] fn main() { trait MaybeFrom<T> { fn maybe_from(value: T) -> Option<Self> where Self: Sized; } }
Трейты могут строиться на требованиях других трейтов. В примере ниже Iterator является супертрейтом, а ThreeIterator — субтрейтом:
#![allow(unused)] fn main() { trait ThreeIterator: Iterator { fn next_three(&mut self) -> Option<[Self::Item; 3]>; } }
Трейты могут использоваться в функциях как параметры:
#![allow(unused)] fn main() { fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug { for elem in it { println!("{elem:#?}"); } } // u8_len_1, u8_len_2 и u8_len_3 эквивалентны fn u8_len_1(val: impl Into<Vec<u8>>) -> usize { val.into().len() } fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize { val.into().len() } fn u8_len_3<T>(val: T) -> usize where T: Into<Vec<u8>>, { val.into().len() } }
Или как возвращаемые типы:
#![allow(unused)] fn main() { fn from_zero_to(v: u8) -> impl Iterator<Item = u8> { (0..v).into_iter() } }
Использование ключевого слова impl в этой позиции позволяет автору функции скрыть конкретный тип как деталь реализации, которая может изменяться без нарушения кода пользователей.
Трейт-объекты
Трейт-объект — это непрозрачное значение другого типа, которое реализует набор трейтов. Трейт-объект реализует все указанные трейты, а также их супертрейты (если есть).
Синтаксис следующий: dyn BaseTrait + AutoTrait1 + ... AutoTraitN. Можно использовать только один BaseTrait, поэтому этот код не скомпилируется:
ⓘ
#![allow(unused)] fn main() { trait A {} trait B {} let _: Box<dyn A + B>; }
Это также не скомпилируется, так как является синтаксической ошибкой: ⓘ
#![allow(unused)] fn main() { trait A {} trait B {} let _: Box<dyn A + dyn B>; }
С другой стороны, это корректно:
#![allow(unused)] fn main() { trait A {} let _: Box<dyn A + Send + Sync>; }
В Справочнике есть больше информации о трейт-объектах, их ограничениях и различиях между редакциями.
Небезопасные трейты
Некоторые трейты могут быть небезопасными для реализации. Использование ключевого слова unsafe перед объявлением трейта используется для обозначения этого:
#![allow(unused)] fn main() { unsafe trait UnsafeTrait {} unsafe impl UnsafeTrait for i32 {} }
Различия между редакциями 2015 и 2018
warning
В редакции 2015 шаблон параметров не был обязательным для трейтов:
#![allow(unused)] fn main() { trait Tr { fn f(i32); } }
Это поведение больше не допустимо в редакции 2018.