Однострочники
Фрагменты, которые распространены, но все же легко забыть. Смотрите Rust Cookbook для получения дополнительной информации.
Строка:
Замысел | Фрагмент |
---|---|
Конкатенация строк | format!("{x}{y}") |
Вывести строку (любое отображение к любой Write) | write!(x, "{y}") |
Разделение по шаблону | s.split(pattern) |
… с &str | s.split("abc") |
… с char | s.split('/') |
… с замыканием | s.split(char::is_numeric) |
Разделение по пробелам | s.split_whitespace() |
Разделение по переводу строки на новую строку | s.lines() |
Разделение по регулярному выражению | Regex::new(r"\s")?.split("один два три") |
Ввод-вывод:
Замысел | Фрагмент |
---|---|
Создание нового файла | File::create(PATH)? |
То же самое, через OpenOptions | OpenOptions::new().create(true).write(true).truncate(true).open(PATH) |
Макросы:
Замысел | Фрагмент |
---|---|
Аргументы Macro | macro_rules! var_args { ($($args:expr),*) => {{ }} } |
Использование args, например, вызов f несколько раз. | $( f($args); )* |
Эзотерика:
Замысел | Фрагмент |
---|---|
Более чистые замыкания | wants_closure({ let c = outer.clone(); move || use_clone(c) }) |
Использование в замыканиях ‘ошибок’ | iter.try_for_each( |x | { Ok::<(), Error>(()) })?; |
Итерация и изменение &mut [T], если T Copy | Cell::from_mut(mut_slice).as_slice_of_cells() |
Получить срез с длиной. | &original_slice[offset..][..length] |
Обеспечение того, чтобы _ trait Т была объектнобезопасной | const _: Option<&dyn T> = None; |
Потокобезопасность
Пример | Send (примечание под таблицей) | не Send |
---|---|---|
Sync* | Большинство типов… Arc<T> , Mutex<T> | MutexGuard<T> , RwLockReadGuard<T> |
Экземпляр t, в котором T: Send можно переместить в другой поток, а T: Sync означает, что &t можно переместить в другой поток.
Итераторы
Использование:
Базовые
Предположим, что у вас есть коллекция c
типа C
:
c.into_iter()
- превращает коллекциюc
в итераторi
и потребляет*c
. ДляC
требуется реализация IntoIterator. Тип элемента зависит от того, каким былC
. Стандартизированный способ получения итераторов.c.iter()
- вежливый метод, предоставляет некоторые коллекции, возвращает заимствование итератора не потребляя c.c.iter_mut()
- то же самое, но мутабельно заимствующий итератор, который позволяет изменять коллекцию.
Итератор
Если у вас итератор i
:
i.next()
- возвращает значение Some(x) следущего элемента или None, если элементы закончились в переборе.
Для циклов
for x in c {}
- синтаксический сахар, вызывает c.into_iter() в цикле возврахая элемент вx
до получения None.
Совместимый итератор
let c = other_iter.collect::<C<_>>()
- соберает итерируемую коллекцию вc
.
Создание итераторов:
Основная тема
Предположим, что у вас есть struct Collection<T> {}
:
struct IntoIter<T> {}
- создаёт структуру для хранения статуса итерации (например, индекса) для итерации значений.impl Iterator for IntoIter<T> {}
- реализует Iterator::next(), чтобы он мог создавать элементы.На данный момент у вас есть что-то, что может вести себя как итератор, но нет способа фактически получить его. Смотрите ниже, чтобы узнать, как это работает.
Общие и изменяемые итераторы
Необходимы, если вы хотите, чтобы ваша коллекция была полезна при заимствовании:
struct Iter<T> {}
- создание структуры удержания&Collection<T>
для общей итерации.struct IterMut<T> {}
- аналогично, но удерживает&mut Collection<T>
для изменяемой итерации.impl Iterator for Iter<T> {}
- реализует общую итерацию.impl Iterator for IterMut<T> {}
- реализует изменяемую итерацию.
Кроме того, можно добавить удобные методы:
Collection::iter(&self) -> Iter
Collection::iter_mut(&mut self) -> IterMut
Предоставление итераторов:
Native Loop Support
Многие пользователи ожидают, что ваша коллекция будет стандартно работать с циклами:
impl IntoIterator for Collection<T> {}
- теперьfor x in c {}
работает.impl IntoIterator for &Collection<T> {}
- теперьfor x in &c {}
работает.impl IntoIterator for &mut Collection<T> {}
- теперьfor x in &mut c {}
работает.Как вы можете видеть, trait IntoIterator - это то, что фактически связывает вашу коллекцию с trait IntoIter, которую вы создали выше.
Совместимость с другими итераторами
Разрешите итераторам 3-й стороны «собирать» коллекцию:
impl FromIterator for Collection<T> {}
- работает какsome_iter.collect::<Collection<_>>()
.
Преобразование чисел
As-correct-as-it-currently-gets числовые преобразования.
Типы | u8 … i128 | f32 / f64 | Строка |
---|---|---|---|
u8 … i128 | u8::try_from(x)? $^1$ | x as f32 $^3$ | x.to_string() |
f32 / f64 | x as u8 $^2$ | x as f32 | x.to_string() |
String | x.parse::<u8>()? | x.parse::<f32>()? | x |
$^1$ Если тип true подмножество from()
работает напрямую, например, u32::from(my_u8)
.
$^2$ Усечение (11.9_f32 as u8
дает 11) и насыщение (1024_f32 as u8
дает 255).
$^3$ Может искажать число u64::MAX as f32
или создавать бесконечность u128::MAX as f32
.
Также см. преобразования и арифметические подводные камни, чтобы узнать больше вещей, которые могут пойти не так при работе с числами.
Преобразование строк
Если вам нужна строка типа …
String
Если у вас есть x типа … | Используйте это … |
---|---|
String | x |
CString | x.into_string()? |
OsString | x.to_str()?.to_string() |
PathBuf | x.to_str()?.to_string() |
Vec<u8> $^1$ | String::from_utf8(x)? |
&str | x.to_string() $^i$ |
&CStr | x.to_str()?.to_string() |
&OsStr | x.to_str()?.to_string() |
&Path | x.to_str()?.to_string() |
&[u8] $^1$ | String::from_utf8_lossy(x).to_string() |
CString
Если у вас есть x типа … | Используйте это … |
---|---|
String | CString::new(x)? |
CString | x |
OsString $^2$ | CString::new(x.to_str()?)? |
PathBuf | CString::new(x.to_str()?)? |
Vec<u8> $^1$ | CString::new(x)? |
&str | CString::new(x)? |
&CStr | x.to_owned() $^i$ |
&OsStr $^2$ | CString::new(x.to_os_string().into_string()?)? |
&Path | CString::new(x.to_str()?)? |
&[u8] $^1$ | CString::new(Vec::from(x))? |
*mut c_char $^3$ | unsafe { CString::from_raw(x) } |
OsString
Если у вас есть x типа … | Используйте это … |
---|---|
String | OsString::from(x) $^i$ |
CString | OsString::from(x.to_str()?) |
OsString | x |
PathBuf | x.into_os_string() |
Vec<u8> $^1$ | ? |
&str | OsString::from(x) $^i$ |
&CStr | OsString::from(x.to_str()?) |
&OsStr | OsString::from(x) $^i$ |
&Path | x.as_os_str().to_owned() |
&[u8] $^1$ | ? |
PathBuf
Если у вас есть x типа … | Используйте это … |
---|---|
String | PathBuf::from(x) $^i$ |
CString | PathBuf::from(x.to_str()?) |
OsString | PathBuf::from(x) $^i$ |
PathBuf | x |
Vec<u8> $^1$ | ? |
&str | PathBuf::from(x) $^i$ |
&CStr | PathBuf::from(x.to_str()?) |
&OsStr | PathBuf::from(x) $^i$ |
&Path | PathBuf::from(x) $^i$ |
&[u8] $^1$ | ? |
Vec<u8>
Если у вас есть x типа … | Используйте это … |
---|---|
String | x.into_bytes() |
CString | x.into_bytes() |
OsString | ? |
PathBuf | ? |
Vec<u8> $^1$ | x |
&str | Vec::from(x.as_bytes()) |
&CStr | Vec::from(x.to_bytes_with_nul()) |
&OsStr | ? |
&Path | ? |
&[u8] $^1$ | x.to_vec() |
&str
Если у вас есть x типа … | Используйте это … |
---|---|
String | x.as_str() |
CString | x.to_str()? |
OsString | x.to_str()? |
PathBuf | x.to_str()? |
Vec<u8> $^1$ | std::str::from_utf8(&x)? |
&str | x |
&CStr | x.to_str()? |
&OsStr | x.to_str()? |
&Path | x.to_str()? |
&[u8] $^1$ | std::str::from_utf8(x)? |
&CStr
Если у вас есть x типа … | Используйте это … |
---|---|
String | CString::new(x)?.as_c_str() |
CString | x.as_c_str() |
OsString $^2$ | x.to_str()? |
PathBuf | ?$^4$ |
Vec<u8> $^1$$^,$$^5$ | CStr::from_bytes_with_nul(&x)? |
&str | ?$^4$ |
&CStr | x |
&OsStr $^2$ | ? |
&Path | ? |
&[u8] $^1$$^,$$^5$ | CStr::from_bytes_with_nul(x)? |
*const c_char $^1$ | unsafe { CStr::from_ptr(x) } |
&OsStr
Если у вас есть x типа … | Используйте это … |
---|---|
String | OsStr::new(&x) |
CString | ? |
OsString | x.as_os_str() |
PathBuf | x.as_os_str() |
Vec<u8> $^1$ | ? |
&str | OsStr::new(x) |
&CStr | ? |
&OsStr | x |
&Path | x.as_os_str() |
&[u8] $^1$ | ? |
&Path
Если у вас есть x типа … | Используйте это … |
---|---|
String | Path::new(x) $^r$ |
CString | Path::new(x.to_str()?) |
OsString | Path::new(x.to_str()?) $^r$ |
PathBuf | Path::new(x.to_str()?) $^r$ |
Vec<u8> $^1$ | ? |
&str | Path::new(x) $^r$ |
&CStr | Path::new(x.to_str()?) |
&OsStr | Path::new(x) $^r$ |
&Path | x |
&[u8] $^1$ | ? |
&[u8]
Если у вас есть x типа … | Используйте это … |
---|---|
String | x.as_bytes() |
String | x.as_bytes() |
OsString | ? |
PathBuf | ? |
Vec<u8> $^1$ | &x |
&str | x.as_bytes() |
&CStr | x.to_bytes_with_nul() |
&OsStr | x.as_bytes() $^2$ |
&Path | ? |
&[u8] $^1$ | x |
другое
Необходимо | делайте x | Используйте это … |
---|---|---|
*const c_char | CString | x.as_ptr() |
$^i$ Краткая форма x.into() возможна, если можно определить тип.
$^r$ Краткая форма x.as_ref() возможна, если можно определить тип.
$^1$ Вы должны или должны, если вызов unsafe
, убедиться, что необработанные данные поставляются с допустимым представлением типа строки (например, данные UTF-8 для string).
$^2$ Только на некоторых платформах существует std::os::<ваша_os>::ffi::OsStrExt
с вспомогательными методами для получения необработанного &[u8]
представления базового OsStr. Используйте остальную часть таблицы, чтобы перейти оттуда, например:
use std::os::unix::ffi::OsStrExt;
let bytes: &[u8] = my_os_str.as_bytes();
CString::new(bytes)?
$^3$ Должно быть, c_char
пришло из предыдущего CString
. Если он исходит из FFI, см. &CStr
вместо этого.
$^4$ Нет известного варианта для x , будет не хватать завершающего 0x0. Лучший способ, вероятно, перейти на CString.
$^5$ Надо убедиться, что вектор действительно заканчивается 0x0.
Вывод строки
Преобразование типов в string или их вывод.
APIs:
Макрос | Вывод | Комментарий |
---|---|---|
format!(fmt) | String | Преобразует в строку. |
print!(fmt) | Console | Записывает в стандартный поток вывода. |
println!(fmt) | Console | Записывает в стандартный поток вывода. |
eprint!(fmt) | Console | Записывает в стандартный поток ошибки. |
eprintln!(fmt) | Console | Записывает в стандартный поток ошибки. |
write!(dst, fmt) | Buffer | Не забудьте использовать std::io::Write; |
writeln!(dst, fmt) | Buffer | Не забудьте использовать std::io::Write; |
Метод | Комментарий |
---|---|
x.to_string() | Создает String, реализованный для любого типа Display. |
fmt
является строковым литералом, таким как “число {}”, который указывает формат вывода (смотрите ниже ‘Форматирование’) и дополнительные параметры.
Типы для печати
В format!
, типы преобразуются через trait Display
”{}” или Debug
”{:?}”, неполный список:
Тип | Реализует |
---|---|
String | Debug, Display |
CString | Debug |
OsString | Debug |
PathBuf | Debug |
Vec<u8> | Debug |
&str | Debug, Display |
&CStr | Debug |
&OsStr | Debug |
&Path | Debug |
&[u8] | Debug |
bool | Debug, Display |
char | Debug, Display |
u8 … i128 | Debug, Display |
f32 , f64 | Debug, Display |
! | Debug, Display |
() | Debug |
Реализация более сложных типов, почти все является Debug;
, для сложных типов может потребовать специальный метод преобразования в Display.
Форматирование
Каждое обозначение аргумента в макросе форматирования либо {} или {argument}, либо следовать базовому синтаксису:
{ [argument] ':' [[fill] align] [sign] ['#'] [width [$]] ['.' precision [$]] [type] }
Элемент | Смысл |
---|---|
argument | Число (0, 1, …), переменная или имя, например, print!("{x}") . |
fill | Символ для заполнения пробелов (например, 0), если указана ширина. |
align | Влево (<), по центру (^) или вправо (>), если указана ширина. |
sign | Может быть + для того, чтобы знак всегда печатался. |
# | Альтернативное форматирование, например, приукрашивание отладочного модуля форматирования ? или префикс шестнадцатеричный с 0x. |
width | Минимальная ширина (≥ 0), заполнение символом (по умолчанию - пробел). Если начинается с 0, начало заполняется нулями. |
precision | Десятичные цифры (≥ 0) для числовых значений или максимальная ширина для нечисловых значений. |
$ | Интерпретирует ширину или точность как идентификатор аргумента, чтобы разрешить динамическое форматирование. |
type | Форматирование отладки (?), шестнадцатеричный (x), двоичный (b), восьмеричный (o), указатель (p), exp (e)… см. далее. |
Пример форматирования | Комментарий |
---|---|
{} | Печать аргумента с помощью команды «Display». |
{x} | То же самое, но использует переменную ‘x’. |
{:?} | Выводит аргумент с помощью отладки. |
{2:#?} | Вывод 3-го аргумента с форматированием отладки. |
{val:^2$} | Центрирует аргумент val, ширина которого задается 3-м аргументом. |
{:<10.3} | Выравнивание по левому краю с шириной 10 и точностью 3. |
{val:#x} | Отформатирует аргумент val как шестнадцатеричный с начальным значением 0x (альтернативный формат для ‘x’). |
Пример | Комментарий |
---|---|
println!("{}", x) | Печать x с помощью Display в стандартный поток вывода. Вывести на консоль и перейти на новую строку. |
println!("{x}") | То же самое, но используйте переменную ‘x’. |
format!("{a:.3} {b:?}") | Возвращает строку преобразования ‘a’ с 3 цифрами после запятой плюс пробел и b с отладкой. |