Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Тема
Описание
Доп.

📌 изучить доступные инструменты cargo

Например, поиск по запросу cargo-<something> «инструменты» выдает десятки результатов

просканируйте свой crate на предмет нарушений семантического версионирования Semver при подготовке к выпуску новой версии.

По сути, он проверяет, не содержит ли новая версия вашего публичного API изменений, которые должны были бы повлечь за собой повышение старшего (major) или среднего (minor) номера версии, но были ошибочно выпущены как патч (patch) или минорное обновление.

crate cargo-udeps

предупреждает вас, когда ваш Cargo.toml включает неиспользуемую зависимость можно добавить в CI

crate cargo-deny

Анализирует ваш граф зависимостей для обнаружения различных потенциальных проблем во всем наборе транзитивных зависимостей:

  • Зависимости, имеющие известные проблемы безопасности во включенной версии
  • Зависимости, которые покрываются неприемлемой лицензиней
  • Зависимости, которые просто неприемлемы
  • Зависимости, включенные в несколько различных версий в дереве зависимостей

можно добавить в CI

cargo-audit

проверка зависимостей на уязвимости безопасности

advisories

cargo generate-lockfile

Cargo-audit - это утилита командной строки, которая проверяет Cargo.lock файлы и сравнивает их с RustSec Advisory Database, базой данных сообщества уязвимостей безопасности, поддерживаемой рабочей группой Rust Secure Code

$ cargo install cargo-audit
$ cargo audit --json

$ cargo generate-lockfile

Чем больше ваш график зависимостей, тем больше вероятность того, что вы столкнетесь с такого рода проблемами. Экосистема крейтов Rust так же уязвима для случайных проблем с зависимостями, как и другие экосистемы пакетов, где история показала, что удаление пакета одним разработчиком или исправление лицензирования для своего пакета командой может иметь широкомасштабные цепные эффекты.

Еще более тревожными являются Атаки на цепочки поставок, когда злоумышленник намеренно пытается подорвать часто используемые зависимости, используя типосквоттинг , захват учетной записи сопровождающего или другие более сложные атаки.

Этот тип атаки влияет не только на ваш скомпилированный код — имейте в виду, что зависимость может запустить произвольный код во время сборки , через build.rs скрипты или процедурные макросы. Это означает, что скомпрометированная зависимость может привести к запуску майнера криптовалюты как части вашей системы CI!

crate cargo-crev

Crate cargo-crev — это инструмент для системы ревизий кода в экосистеме Rust. Его основная цель — повысить доверие к коду, используемому в зависимости, и помочь разработчикам выбирать безопасные и качественные библиотеки.

Even Better TOML

Это расширение для Vs code показывает актуальные версии пакетов

rustc - компилирует исполняемый файл

command-line-arguments

# Версия компилятра
rustc --version

# компиляция завершение процесса программы при panic! (нужна OC abort)
rustc --cfg 'panic="abort"' src/main.rs

# запуск
./main

# или компиляция и запуск 
rustc src/parse_sound.rs && ./parse_sound

Пакетный менеджер выполняет rustc.

Cargo, менеджер пакетов Rust, позволяет автоматически выбирать зависимости для кода Rust в соответствии с семантическое версионирование (semver)

Позволяет "package" объявлять свои различные зависимости и гарантировать, что вы всегда получите повторяемую сборку.

Три задачи: сборка кода, загрузка библиотек, от которых зависит ваш код, и сборка этих библиотек

Cargo.lock - содержит точную информацию о том, какую версию всех зависимостей мы использовали.

Install:

curl https://sh.rustup.rs -sSf | sh
PATH=$PATH:/home/jeka/.cargo/bin

Установить Cargo

other-installers

$ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly

curl https://sh.rustup.rs -sSf | sh -s -- -y

# sudo mount -o remount,exec /tmp # если папка смонтирована как noexec

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 

export PATH="$PATH:$HOME/.cargo/bin"

sudo apt-get install build-essential # доп. пакеты

sudo apt-get install libc6-dev
sudo apt-get install libssl-dev

Удалить Cargo

rustup self uninstall

sudo apt remove --auto-remove --purge rust-gdb rustc libstd-rust-1.24 libstd-rust-1.28 libstd-rust-dev

Создание пустого проекта (bin по умолчанию)

$ cargo new --bin hello_world (или $ cargo new hello_world)
$ cargo build // смотри $ ./target/debug/hello_world
$ cargo run 
$ cargo build --release // смотри $ ./target/release/hello_world

$ cargo new --lib mylib # создаст lib.rs и папку .git
$ cargo new --vcs none --lib mylib  # создаст lib.rs  без папки .git

или из clon
$ git clone https://github.com/rust-lang-nursery/rand.git
$ cd rand
$ cargo build

$ cargo +nightly new hello-world --edition 2018

Обновить определенный пакет

Ошибка

error[E0282]: type annotations needed for Box<_>
  --> /home/jeka/.cargo/registry/src/index.crates.io-6f17d22bba15001f/time-0.3.34/src/format_description/parse/mod.rs:83:9
   |
83 |     let items = format_items
   |         ^^^^^
...
86 |     Ok(items.into())
   |              ---- type must be known at this point
   |
   = note: this is an inference error on crate time caused by an API change in Rust 1.80.0; update time to version >=0.3.35 by calling cargo update

Поскольку в вашем проекте используется версия библиотеки time 0.3.34, которая несовместима с последней версией компилятора Rust, вам необходимо обновить зависимость библиотеки time до версии 0.3.35 или выше, где эта проблема уже исправлена.

cargo update -p time
cargo build

указывает, cargo какие диапазоны версий semver приемлемы для этой зависимости

specifying-dependencies

effective-rust/semver

code-security/dependabot

Избегайте указания полностью Wildcard-зависимость, например "*" или "0.*"
Полностью wildcard-зависимость говорит, что любая версия зависимости с любым API может использоваться вашим контейнером, что вряд ли будет тем, что вам нужно. 

"1.2.3": Указывает, что приемлема любая версия, совместимая с semver 1.2.3
"^1.2.3": Это еще один способ более явно указать то же самое
"=1.2.3": Прикрепляет к одной конкретной версии, замены не допускаются
"~1.2.3": Разрешает версии, совместимые с semver 1.2.3, но только в тех случаях, когда изменяется последний указанный компонент (поэтому 1.2.4 приемлема, а 1.3.0 — нет)
"1.2.*": Принимает любую версию, соответствующую подстановочному знаку

Версия "1" эквивалентна "^1", которая допускает все версии 1.x (и поэтому также эквивалентна "1.*")
Версия "1.4.23" эквивалентна "^1.4.23", что допускает любые версии 1.x, превышающие 1.4.23

Учитывая номер версии MAJOR.MINOR.PATCH, увеличьте:
MAJOR версия при внесении несовместимых изменений в API
MINOR версия, когда вы добавляете функциональность с обратной совместимостью
PATCH версия, когда вы делаете исправления ошибок с обратной совместимостью

После выпуска версии пакета содержимое этой версии НЕ ДОЛЖНО быть изменено. Любые изменения ДОЛЖНЫ быть выпущены как новая версия.

Такие инструменты, как cargo update или Dependabot может информировать вас о доступности обновлений; затем вы можете запланировать обновление на удобное для вас время.
Спецификация" 1.2.2 "" 1.2.3 "" 1.2.4 "" 1.3.0 "" 2.0.0 "
"1.2.3"НетДаДаДаНет
"^1.2.3"НетДаДаДаНет
"=1.2.3"НетДаНетНетНет
"~1.2.3"НетДаДаНетНет
"1.2.*"ДаДаДаНетНет
"1.*"ДаДаДаДаНет
"*"ДаДаДаДаДа

Поймите, что добавление зависимостей экономит время на написание кода, но это не бесплатно.

dep-graph.html#what-to-depend-on

Однако каждая новая зависимость имеет свою цену, частично из-за более длительных сборок и больших двоичных файлов, но в основном из-за усилий разработчиков, затрачиваемых на устранение проблем с зависимостями по мере их возникновения.

Используйте Re-export для зависимостей вашей библиотеки

повторно экспортируйте зависимости, типы которых появляются в вашем API

effective-rust/re-export

Кстати, подумайте хорошенько, прежде чем использовать типы другого ящика в вашем API : это тесно связывает ваш ящик с ящиком зависимости. Например, повышение основной версии для зависимости автоматически потребует повышения основной версии и для вашего ящика.

т.е. если ваш публичный API метод явно требует зависимости от внешней библиотеки pub fn foo(item: some_extern_lib::ExternStruct){} то другой код использующий вашу библиотеку и crate some_extern_lib с более новой версией не смогут сосуществовать. Думаю можно спрятать зависимость за своей обверткой и не выдавать зависимость наружу, создав ее самостоятельно

С точки зрения автора бинарного файла, проблему можно обойти, добавив промежуточный контейнер-обертку, который скрывает открытое использование rand типов v0.7. Контейнер-обертка отличается от бинарного контейнера и поэтому может зависеть от rand v0.7 отдельно от зависимости бинарного контейнера от rand v0.8

Лучший подход доступен автору библиотечного ящика. Он может облегчить жизнь своим пользователям, явно реэкспорт одного из следующих:

  • Типы, задействованные в API
  • Весь ящик зависимостей
// Re-export the version of `rand` used in this crate's API.
pub use rand;

т.е. если в используемой внешней библиотеке есть Re-export то эти зависимости с другой версией будет возможно использовать через имя библиотеки

some_lib::rand и при этом свою зависимость rand можно будет использовать другой версии напрямую в своей библиотеке/бинарном файле

избегать импорта подстановочных знаков ::* из контейнеров

effective-rust/wildcard

избегать импорта подстановочных знаков из контейнеров, которые вы не контролируете

use somecrate::module::* говорит о том, что каждый публичный символ из этого модуля должен быть добавлен в локальное пространство имен.

зависимость добавит новый символ, который будет конфликтовать с именем, которое вы уже используете? Если какие-либо имена методов из нового типажа конфликтуют с существующими именами методов, которые применяются к типу, то компилятор больше не может однозначно определить, какой метод имеется в виду

Глобальные зависимости

cargo-home

$HOME/.cargo/

Конфигурация проекта config.toml

reference/config

configuration-format

.cargo/ - Конфигурация груза локального проекта , может содержать . config.toml

/projects/foo/.cargo/config.toml
/projects/.cargo/config.toml
$HOME/.cargo/config.toml

# быстрая компиляция
[registries.crates-io] 
protocol = "sparse"

[doc]
browser = "chromium"          # browser to use with `cargo doc --open`

[env]
# Set ENV_VAR_NAME=value for any process run by Cargo
ENV_VAR_NAME = "value"
# Set even if already present in environment
ENV_VAR_NAME_2 = { value = "value", force = true }

Cargo также можно настроить с помощью переменных среды в дополнение к файлам конфигурации TOML

Некоторые пакеты требуют компиляции стороннего кода, отличного от Rust, например библиотеки C. Cargo скомпилирует build.rs скрипт и выполнит его непосредственно перед сборкой пакета.

Некоторые примеры использования скриптов сборки:

  • Создание связанной библиотеки C.
  • Поиск библиотеки C в хост-системе.
  • Создание модуля Rust из спецификации.
  • Выполнение любой конфигурации для конкретной платформы, необходимой для ящика.

Cargo.toml:

[package]
name = "secure_code"
version = "0.1.0"
edition = "2021"
build = "build.rs"

File /build.rs:


use std::env;
use std::process::Stdio;
fn main() -> Result<(), Box> {
    let mut child = std::process::Command::new("sh")
      .arg("db/setup_db.sh")
      .stderr(Stdio::piped())
      .spawn()
      .unwrap();
    child.wait().unwrap();
   Ok(())
}

build.rs для gRPC:


use std::env;
use std::path::PathBuf;

fn main() -> Result<(), Box> {
   let proto_file = "./proto/store.proto";
   let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

   tonic_build::configure()
           .protoc_arg("--experimental_allow_proto3_optional") // for older systems
           .build_client(true)
           .build_server(true)
           .file_descriptor_set_path(out_dir.join("store_descriptor.bin"))
           .out_dir("./src")
           .compile(&[proto_file], &["proto"])?;

   Ok(())
}

Версия компилятора при запуске

В корень проекта файл, который будет управлять версией компилятора:

$ cat rust-toolchain.toml 
[toolchain]
channel = "nightly-2022-06-09"

Если такой версии компилятора на компе нет, то cargo вызовет rustup, чтобы тот поставил нужную версию. Если такой компилятор есть, то любые действия с cargo по компиляции будут использовать указанную в конфиге версию.

Формат манифеста

Cargo.toml

the-manifest-format

[package]
name = "social_backend"
version = "0.1.0-dev"
edition = "2018"
description = "Backend part of social platform project."
authors = ["Instrumentisto Team <developer@instrumentisto.com>"]
readme = "README.md"
repository = "https://git.instrumentisto.com/social/backend"
publish = false

[dependencies]
postgres_macros = "0.1" // из ветки master залитой на crates.io
postgres_macros = { path = "../postgres_macros-0.1.13"} // из своей папки
postgres_macros = { git = "https://github.com/sfackler/rust-postgres-macros.git", rev = "7d4cc509e5c96e062ba494ecd7fde020a5e91a21" } // из ветки master определенного commit

[dependencies.postgres_macros]   // из ветки release определенного commit
  git="https://github.com/sfackler/rust-postgres-macros.git"
   branch = "release"
   version = "0.1.12"
   rev = "fbe8fb80cb5e5873b611b6203c56a2d8279f6296"

[dev-dependencies]
# Dev-зависимости не используются при компиляции пакета для сборки, но используются для компиляции тестов, примеров и тестов производительности.

[dev-dependencies]

[dev-dependencies] - Зависимости для примеров, тестов и бенчмарков.

Dev-зависимости не используются при компиляции пакета для сборки cargo build, но используются для компиляции тестов, примеров и тестов. Эти зависимости не распространяются на другие пакеты, зависящие от этого пакета.

[dev-dependencies]
tempdir = "0.3"

[workspace]

workspaces

Рабочая область — это набор из одного или нескольких пакетов, называемых членами рабочей области, которые управляются вместе.

Настройка сборки

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3 // opt-level  - это количество оптимизаций с диапазоном от 0 до 3


[profile.dev]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 16
panic = 'unwind'
incremental = true
overflow-checks = true

[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
panic = 'abort'
incremental = false
overflow-checks = false

[profile.test]
opt-level = 0
debug = 2
rpath = false
lto = false
debug-assertions = true
codegen-units = 16
incremental = true
overflow-checks = true

[profile.bench]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 16
incremental = false
overflow-checks = false

Профили [profile.dev]

cargo build --profile=dev

profiles

Cargo имеет 4 встроенных профиля: dev, release, test, и bench . Профиль выбирается автоматически на основе выполняемой команды, если профиль не указан в командной строке.

Дефолтный cargo build:

[profile.dev]
opt-level = 0
debug = true
split-debuginfo = '...'  # Platform-specific.
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false

Дефолтный cargo build --release:

[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...'  # Platform-specific.
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false

сколько времени заняла компиляция каждого контейнера

cargo build --timings

cargo build --timings (или cargo run --timings)

сгенерирует удобный отчет в формате HTML, который покажет вам, сколько времени заняла компиляция каждого контейнера.

Project Layout

.
├── Cargo.lock
├── Cargo.toml
├── src/
│   ├── lib.rs
│   ├── main.rs
│   └── bin/
│       ├── named-executable.rs
│       ├── another-executable.rs
│       └── multi-file-executable/
│           ├── main.rs
│           └── some_module.rs
├── benches/
│   ├── large-input.rs
│   └── multi-file-bench/
│       ├── main.rs
│       └── bench_module.rs
├── examples/
│   ├── simple.rs
│   └── multi-file-example/
│       ├── main.rs
│       └── ex_module.rs
└── tests/
    ├── some-integration-tests.rs
    └── multi-file-test/
        ├── main.rs
        └── test_module.rs

  • Cargo.toml и Cargo.lock размещается в корневой директории вашего проекта.
  • Исходный код отправляется в директорию src.
  • Стандартный файл библиотеки расположен по адресу src/lib.rs.
  • Стандартный исполняемый файл находится по адресу src/main.rs.
  • Другие исполняемые файлы могут быть расположены в src/bin/*.rs.
  • Интеграционные тесты находятся в директории tests (юнит тесты в том файле, который они тестируют).
  • Исполняемые примеры располагаются в директории examples.
  • Бенчмарки хранятся в директории benches
  • Скомпилированный исполняемый файл в target/debug/<name project> или target/release/<name project>

Замена для extern crate foo as bar;

[dependencies.baz]
version = "0.1"
package = "foo"

[dependencies]
baz = { version = "0.1", package = "foo" }

Избегайте необходимости use foo as bar в Rust source.

Зависит от нескольких версий ящика.

Зависит от ящиков с одинаковым названием из разных реестров.

renaming-dependencies-in-cargotoml

Все три библиотеки одно и тоже из разных источников Для поддержки этого Cargo поддерживает package ключ в [dependencies] разделе, от которого должен зависеть пакет: т.е. явно с помощью package ключа указать как называется библиотека который мы хотим получить, а то как мы ее назовем тут baz = {...

[package]
name = "mypackage"
version = "0.0.1"

[dependencies]
foo = "0.1"
bar = { git = "https://github.com/example/project", package = "foo" }
baz = { version = "0.1", registry = "custom", package = "foo" }

В этом примере три ящика теперь доступны в вашем коде Rust:

extern crate foo; // crates.io
extern crate bar; // git repository
extern crate baz; // registry `custom`

Все три из этих ящиков имеют название пакета foo в своем собственном Cargo.toml, так что мы явно с помощью package ключа , чтобы сообщить Cargo , что мы хотим , чтобы foo пакет , даже если мы называем это что-то еще на месте. Если package ключ не указан, по умолчанию используется имя запрашиваемой зависимости.

Обратите внимание, что если у вас есть необязательная зависимость, например:

[dependencies]
foo = { version = "0.1", package = 'bar', optional = true }

Вы bar зависите от ящика от crates.io, но у вашего ящика есть foo функция вместо bar функции. То есть имена функций принимают после имени зависимости, а не имени пакета, при переименовании.

Создает графы зависимостей

cargo-deps

cargo-depgraph

cargo-depgraph

cargo-deps

graphviz

Создавайте диаграммы зависимостей для ваших проектов

cargo install cargo-deps
sudo apt install graphviz

cargo deps | dot -Tpng > graph.png

cargo deps --all-deps | dot -Tpng > graph.png

cargo install cargo-depgraph

cargo depgraph [options] | dot -Tpng > graph.png

информацию о структуре проекта и зависимостях в JSON

machine-readable-output

jsonviewer.stack.hu

Show json jsoneditoronline.org

$ cargo metadata > /home/jeka/file.json

Output:

{
  // Версия формата сообщений .
  "version": integer,

  // Список пакетов для проекта, включая зависимости.
  "packages": [
    {
      // Уникальный идентификатор пакета.
      "id": PackageId,
      "name": string,
      "version": string,
      "source": SourceId,

      // Список объявленных зависимостей. Используемые зависимости описаны в пол `resolve`.
      "dependencies": [ Dependency ],

      "targets: [ Target ],

      // Путь до Cargo.toml
      "manifest_path": string,
    }
  ],
  "workspace_members": [ PackageId ],

  // Граф зависимостей.
  "resolve": {
     "nodes": [
       {
         "id": PackageId,
         "dependencies": [ PackageId ]
       }
     ]
  }
}

Реальные зависимости проекта

Cargo.toml

Cargo.lock

cargo tree --format "{p} {f}"
cargo tree -f '{p} {f}'

cargo build -v
cargo update

Указание синтаксиса зависимостей:

.gitignore cargo.lock:

Если вы создаете не конечный продукт, например библиотеку rust, от которой будут зависеть другие пакеты rust, вставьте Cargo.lock свой .gitignore. Если вы создаете конечный продукт, исполняемый как инструмент командной строки или приложение, или системную библиотеку с типом ящика staticlib или cdylib, отметьте Cargo.lock в git


Cargo.toml:

[dependencies]
regex = "0.1.41" # пожелание по умолчанию ^0.1.41  Для точной версии "=0.1.41"

Cargo.lock содержит точную информацию о том, какую версию всех зависимостей мы использовали, чтобы сборка была стабильной и не требовала новых загрузок

Передавать файлы Cargo.lock в .gitignore систему контроля версий или нет? То, что производит конечный продукт, а именно приложения и двоичные файлы, должно передаваться с Cargo.lock для обеспечения детерминированной сборки. Библиотечные контейнеры не должны передавать файл Cargo.lock, поскольку он не имеет значения для последующих потребителей библиотеки — у них будет свой собственный файл Cargo.lock имейте в виду, что файл Cargo.lock для библиотечного контейнера игнорируется пользователями библиотеки Однако, если вы контролируете версии Cargo.lock, настройте процесс для обработки обновлений (например, GitHub's Dependabot)

[[package]]
name = "regex"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
dependencies = ["aho-corasick", "memchr", "regex-syntax", "thread_local","utf8-ranges",]
$ cargo tree 
temp v0.1.0 (/home/jeka/projects/project_rust/temp)
└── regex v0.1.80
    ├── aho-corasick v0.5.3
    │   └── memchr v0.1.11
    │       └── libc v0.2.97
    ├── memchr v0.1.11 (*)
    ├── regex-syntax v0.3.9
    ├── thread_local v0.2.7
    │   └── thread-id v2.0.0
    │       ├── kernel32-sys v0.2.2
    │       │   └── winapi v0.2.8
    │       │   [build-dependencies]
    │       │   └── winapi-build v0.1.1
    │       └── libc v0.2.97
    └── utf8-ranges v0.1.3

просил regex 0.1.4 но cargo дал 0.1.8 так как это минимальная разрешимая версия используемая другими пакетами т.е по факту в проекте версия 0.1.8 хотя Cargo.toml написано 0.1.4 cargo build -v покажет версии пакетов в сборке ...Compiling regex v0.1.80

Теперь, если regex будет обновлено, мы по-прежнему будем строить с той же ревизией, пока не выберем cargo update

cargo tree Распечатайте дерево зависимостей

Распечатайте дерево зависимостей:

  • --invert: показывает, что зависит от конкретного пакета, помогая вам сосредоточиться на конкретной проблемной зависимости
  • --edges features: показывает, какие функции ящика активируются ссылкой зависимости, что помогает вам понять, что происходит с унификацией функций
  • --duplicates: Показывает ящики, имеющие несколько версий, представленных в графике зависимостей.
cargo tree -e features

cargo tree --format "{p} {f}"

crate cargo-tree

Дубликаты зависимостей

помогает найти все места, в которые вставляются дубликаты зависимостей

cargo install cargo-tree

$ cargo tree --features serde_json -p libc -i

$ cargo tree -d   

$ tree -d -L 1 target/doc/

cargo tree также может работать в «обратном» режиме, когда дерево зависимостей идет назад. Это чаще всего полезно при попытке определить, откуда поступает определенный ящик. --package или -p флаг выбирает ящик, чтобы использовать в качестве корня дерева и --invert или -i флаг инвертирует граф зависимостей обхода

Cargo.lock

помощь с версией пакета через git (rev, tag, branch)

specifying-dependencies-from-git-repositories

Для точной версии указывается его commit

[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand.git", rev = "9f35b8e" }

но это накладно следить за SHA-1 каждый раз, когда мы хотим обновить нашу библиотеку. Это утомительно и чревато ошибками.

Как это решает cargo.lock за нас, когда у нас есть:

[package]
name = "hello_world"
version = "0.1.0"

[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand.git" }

Cargo возьмет последний коммит и запишет эту информацию в наш, Cargo.lock:

[[package]]
name = "hello_world"
version = "0.1.0"
dependencies = [
 "rand 0.1.0 (git+https://github.com/rust-lang-nursery/rand.git#9f35b8e439eeedd60b9414c58f389bdc6a3284f9)",
]

[[package]]
name = "rand"
version = "0.1.0"
source = "git+https://github.com/rust-lang-nursery/rand.git#9f35b8e439eeedd60b941

Теперь, когда вы передаете свой пакет кому-то другому, он будет использовать тот же самый SHA, даже если мы не указали его в нашем Cargo.toml

$ cargo update

// Обновление только одного пакета
$ cargo update -p rand --precise $version  

// Обновление всех пакетов
$ cargo update                                                                                                                                                                                                                                                                                                                                                                                           

Переопределение зависимостей

[replace] -> [path]

Устарел синтаксис replace вместо него path

specifying-dependencies

overriding-dependencies

Допустим, вы работаете над проектом, используя контейнер uuid, который зависит от rand. Вы обнаружили ошибку в rand, и она уже исправлена, по пока не опубликована.

[dependencies]
uuid = "0.2"

Чтобы переопределить зависимость rand контейнера uuid, мы будем использовать [секцию [replace]] replace-section в Cargo.toml, добавив это в конце:

[replace]
"rand:0.3.14" = { git = 'https://github.com/rust-lang-nursery/rand' }

Посмотреть в Cargo.lock какую конкретно версию использует uuid библиотеке rand:0.3.14

Это означает, что rand версии 0.3.14, которую мы сейчас используем, будет заменена веткой master репозитория rand на GitHub.


Устарел синтаксис replace вместо него path

[patch.crates-io]
rustc-serialize = {path="../rustc-serialize", version="0.3.24"}

feature позволят включать функционал библиотеки

reference/features

Файл библиотеки lib.rs:

//#[cfg(feature = "mydefault")]
//pub use def::*;
pub fn qwerty(){ println!("qwerty");}
#[cfg(feature = "ex_1")]
pub mod bla{
    pub fn boo(){ println!("boo"); }
}
pub mod lala{
    pub fn foo(){ println!("foo");}
}
#[cfg(feature = "mydefault")]
pub mod def{
    pub fn ggg(){ println!("ggg"); }
}

Cargo.toml:

[package]
name = "mylib"
version = "0.1.0"
edition = "2018"

[dependencies]

[features]
default = ['mydefault']
ex_1=[]
mydefault = []

Для использования различных функций библиотеки mylib в своем проекте:

Cargo.toml:
[dependencies]
mylib = {default-features = false,path="mylib",features=["mydefault","ex_1"]}

Файл main.rs:

use mylib::*;
fn main(){
  qwerty();
  def::ggg();
  lala::foo();
  bla::boo();
}

Взаимоисключающие функции

В редких случаях функции могут быть несовместимы друг с другом.

Добавления ошибки компиляции для обнаружения этого сценария.

#[cfg(all(feature = "foo", feature = "bar"))]
compile_error!("feature \"foo\" and feature \"bar\" cannot be enabled at the same time");

Проверка компиляции

Когда сборка долгая, можно проверить компилируется ли проект

cargo check 
cargo check -p <pkgid>
cargo install --list
cargo install mdbook-mermaid
cargo uninstall mdbook-mermaid

cargo-install-for-easy-installation-of-tools

Эта команда управляет локальным набором установленных бинарных крейтов Cargo. Могут быть установлены только пакеты, у которых есть исполняемый файл [[bin]] или [[example]] цели, и все исполняемые файлы устанавливаются в корневую bin папку установки. По умолчанию устанавливаются только двоичные файлы, а не примеры.

Короче устанавливает в систему исполняемые crates

$ cargo install ripgrep

cargo install --path . (для текущего пути)

ch14-04-installing-binaries

cargo install diesel_cli

Команда cargo install позволяет устанавливать и использовать бинарные crate локально. Это не предназначено для замены системных пакетов; он должен быть удобным способом для разработчиков Rust, чтобы установить инструменты, которые другие поделили на crates.io

Все установленные бинарные файлы cargo install хранятся в папке bin корневого каталога установки . Если вы установили Rust с помощью rustup.rs и не имеете каких-либо пользовательских конфигураций, этот каталог будет $HOME/.cargo/bin. Убедитесь, что в вашем каталоге есть $PATH программа для запуска программ, с которыми вы установили cargo install.

Существует реализация Rust grep инструмента, предназначенного ripgrep для поиска файлов. Если мы хотим установить ripgrep, мы можем запустить следующее:

$ cargo install ripgrep
... Installing ~/.cargo/bin/rg

Пока каталог установки находится в вашем $PATH, как упоминалось ранее, вы можете запустить rg --help и начать использовать более быстрый, более простой инструмент для поиска файлов!

Если имя бинарного файла в вашем $PATH имени cargo-something, вы можете запустить его, как если бы это была подкоманда Cargo, запустив ее cargo something

cargo build --timings

предоставляет некоторую информацию о том, сколько времени занимает каждая компиляция

target/cargo-timings/cargo-timing.html

Проверка сборки для определенной цели

cargo build --target wasm32-unknown-unknown

cargo check --target wasm32-unknown-unknown

add-wasm-support-to-crate

cargo build --verbose

сборка dev (developer), исполняемый файл в target/debug/<NAME PROJECT>

cargo build --release

сборка release, для пользователей финальная версия с оптимизацией, исполняемый файл в target/release/<NAME PROJECT>

cargo build --bin my_other_bin

два двоичных файла src/bin/my_other_bin.rs

foo
├── Cargo.toml
└── src
    └── main.rs

Предположим, что мы хотим иметь два двоичных файла в одном проекте. Что тогда?

Оказывается, cargo это поддерживает. Двоичный файл по умолчанию называется main.rs, это мы видели раньше, но вы можете добавить дополнительные файлы, поместив их в bin/ каталог:

foo
├── Cargo.toml
└── src
    ├── main.rs
    └── bin
        └── my_other_bin.rs

Чтобы сказать cargo скомпилировать или запустить этот двоичный файл, мы просто передаём cargo флаг --bin my_other_bin, где my_other_bin это имя двоичного файла, с которым мы хотим работать.

sudo cargo build --verbose > cargo.log 2>&1

  • > Это оператор перенаправления вывода. Он отправляет стандартный вывод (STDOUT) команды в файл.

  • cargo.log Имя файла, в который будет записан стандартный вывод (STDOUT).

  • 2>&1 Это оператор перенаправления потока ошибок (STDERR). Он перенаправляет поток ошибок в то же место, куда перенаправлен стандартный вывод (то есть в файл cargo.log).

cargo run -q --release

Тихий запуск, без лишнего вывода в консоль

cargo run --verbose

Полный список вызываемых команд rustc

cargo run --bin example_bin

Если надо запустить main.rs то в опции --bin указать имя проекта (из Cargo.toml)

Для проверки работы библиотеки:

  • создать папку src/bin/example_bin.rs
  • импортировать свою библиотеку use self::your_lib_name::*;
  • запуск cargo run --bin example_bin

Запуск одного приложения из разных источников

cargo run

Запуск одного приложения из разных источников

Cargo.toml:
[package]
....
default-run = "main"

[[bin]]
name = "main"
path = "src/main.rs"

[[bin]]
name = "websocket-server"
path = "src/main.rs"

[[bin]]
name = "websocket-client"
path = "src/client.rs"

Запуск:

 cargo run // запуститься по дефолту main.rs
 cargo run --bin websocket-server
 cargo run --bin websocket-client

cargo run --example parse_select

Должна быть папка examples/parse_select.rs на уровне с Cargo.toml

cargo run --example parse_select

или

Псевдоним можно указать в Cargo.toml:

[[example]]
name = "parse"
path ="examples/parse_select.rs"

Запуск

cargo run --example parse

cargo run --example parse_select

crate-type

reference/examples

Вы можете запустить отдельные исполняемые примеры с помощью команды cargo run --example <example-name>

По умолчанию примеры - это исполняемые двоичные файлы (с main() функцией). Вы можете указать crate-type поле, чтобы пример был скомпилирован как библиотека: Укажите, crate-type чтобы пример был скомпилирован в виде библиотеки (дополнительная информация о типах ящиков доступна в Справочнике по Rust ):

[[example]]
name = "foo"
crate-type = ["staticlib"]

Вы можете создавать отдельные примеры библиотек с помощью команды cargo build --example <example-name>

cargo run --example image-fractal

cargo run --example image-next

File examples/fractal.rs

Cargo.toml:

[[example]]
name = "image-fractal"
path ="examples/image/fractal.rs"

[[example]]
name = "image-next"
path ="examples/image/next.rs"

Запуск библиотеки на выполнение из папки bin/ как входной файл

Запуск библиотеки на выполнение из папки bin/ как входной файл

Cargo.toml:

[package]
name = "HELLO"

src/lib.rs:

pub mod foo;

src/foo.rs:

pub const VAR:i32 = 9;

src/bin/backend.rs:

fn main() {
    println!("{}",HELLO::foo::VAR);
}

Запуск:

$ cargo run --bin backend

Второй вариант через [[bin]]

Cargo.toml:

[[bin]]
name = "name_run"
path = "src/bin/backend.rs"

Запуск:

$ cargo run --bin name_run

Запуск библиотеки на выполнение из workspace

cargo run -- --workspace ./byte_sized

File test_lib/Cargo.toml:

[workspace]
members = [
    "bin_world",
    "hello_world",
]

test_lib/bin_world (это бинарный проект)

File test_lib/bin_world/src/main.rs :

use hello_world;
fn main() {
    println!("Hello, world! {}",hello_world::foo::Var);
}

File test_lib/bin_world/Cargo.toml (подключает библиотеку hello_world из workspace)

[dependencies]
hello_world = { path = "../hello_world" }

test_lib/hello_world (это библиотека)

File test_lib/hello_world/src/lib.rs:

pub mod foo;

File test_lib/hello_world/src/foo.rs:

pub const Var:i32 = 9;

Сборка и запуск:

../test_lib $ cargo build

../test_lib $ cargo run -p bin_world  // запуск бинарного проекта

cargo +nightly rustc --profile=check -- -Zunpretty=expanded

cargo-expand

выводит текст кода на экран


use quux::{quux_1, quux_2};
use set_example::check_value;
fn main() {
    let mut y = 2;
    {
        let x = || { 7 + y };
        let retval = quux_1(&x);
        { ::std::io::_print(format_args!("retval: {0:?}\n", retval)); };
        let retval = quux_2(x());
        { ::std::io::_print(format_args!("retval: {0:?}\n", retval)); };
    }
    y = 5;
    { ::std::io::_print(format_args!("y     : {0:?}\n", y)); };
    let mut loop_count = 0;
    let p1 = 1;
    loop {
        let p2 = "hello";
        check_value(p1, p2);
        loop_count += 1;
        if loop_count > 2 { break; }
    }
}

cargo +nightly rustc --profile=check -- -Zunpretty=expanded

Использование rust-toolchain.toml позволяет стандартизировать и упрощать процесс управления версиями Rust и связанных инструментов в проекте, что способствует стабильности и предсказуемости разработки.

[toolchain]
channel = "stable"  # Можно указать также "nightly" или конкретную версию, например, "1.56.0"
components = ["rustfmt", "rust-analyzer", "clippy"]  # Дополнительные компоненты для установки
targets = ["wasm32-unknown-unknown"]  # Дополнительные цели компиляции
profile = "minimal"  # Профиль установки, может быть "default", "minimal", или "complete"
  • channel: Указывает версию Rust, которую следует использовать. Это может быть stable, beta, nightly или конкретная версия, например, 1.56.0.

  • components: Список дополнительных компонентов, которые будут установлены вместе с компилятором Rust. Примеры: rustfmt (для форматирования кода), clippy (для анализа кода), rust-src (исходный код стандартной библиотеки).

  • targets: Список дополнительных целей компиляции, которые будут установлены. Например, wasm32-unknown-unknown для компиляции в WebAssembly.

  • profile: Профиль установки Rust. Возможные значения: default (включает большинство компонентов), minimal (только компилятор и Cargo), complete (все доступные компоненты).


Версия компилятора при запуске

В корень проекта файл, который будет управлять версией компилятора:

File rust-toolchain.toml:

[toolchain]
channel = "nightly-2022-06-09"

Если такой версии компилятора на компе нет, то cargo вызовет rustup, чтобы тот поставил нужную версию. Если такой компилятор есть, то любые действия с cargo по компиляции будут использовать указанную в конфиге версию.

Код Rust использует змеиный регистр (snake case) как основной стиль для имён функций и переменных, в котором все буквы строчные, а символ подчёркивания разделяет слова.

📌 Заюзать пример шаблона чистого кода

cucumber/clippy

vscode settings.json

Настройка форматирования IDE vscode

gist

home/jeka/.config/Code/User/settings.json

settings.json
{

    "workbench.colorTheme": "Default Dark+",

    "editor.minimap.enabled": false,

    "scm.inputFontSize": 10,

    "screencastMode.fontSize": 48,

    "debug.console.fontSize": 10,

    "markdown.preview.fontSize": 10,

    "cmake.configureOnOpen": true,

    "idf.flashType": "UART",

    "window.menuBarVisibility": "toggle",

    "workbench.statusBar.visible": false,

    "workbench.tree.indent": 6,

    "workbench.view.alwaysShowHeaderActions": true,

    //"editor.mouseWheelZoom": true ,

    //"files.autoSave": "afterDelay",

    //"editor.fontSize": 8,

    //"terminal.integrated.fontSize": 10,

    // Определяет семейство шрифтов.
    "editor.fontFamily": "Consolas, 'Courier New', monospace",

    // Управляет насыщенностью шрифта.
    "editor.fontWeight": "normal",

    // Управляет размером шрифта в пикселях.
    "editor.fontSize": 8,

    // Управляет высотой строк. Укажите 0 для вычисления высоты строки по размеру шрифта.
    "editor.lineHeight": 0,

    // Управляет видимостью номеров строк.
    "editor.lineNumbers": "on",

    // Столбцы, в которых должны отображаться вертикальные линейки
    "editor.rulers": [],

    // Символы, которые будут использоваться как разделители слов при выполнении навигации или других операций, связанных со словами.
    "editor.wordSeparators": "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?",

    // Число пробелов в табуляции. Эта настройка переопределяется на основании содержимого файла, когда включен параметр "editor.detectIndentation".
    "editor.tabSize": 4,

    // Вставлять пробелы при нажатии клавиши TAB. Эта настройка переопределяется на основании содержимого файла, когда включен параметр "editor.detectIndentation".
    "editor.insertSpaces": true,

    // При открытии файла editor.tabSize и editor.insertSpaces будут определяться на основе содержимого файла.
    "editor.detectIndentation": true,

    // Определяет, будут ли выделения иметь скругленные углы.
    "editor.roundedSelection": true,

    // Определяет, будет ли содержимое редактора прокручиваться за последнюю строку.
    "editor.scrollBeyondLastLine": true,

    // Определяет число символов, после которых текст будет перенесен на следующую строку. Если этот параметр имеет значение 0, используется перенос по ширине окна просмотра (перенос по словам). Если задать значение –1, то в редакторе не будет выполняться перенос по словам.
    "editor.wrappingColumn": 300,

    // Определяет, должны ли строки переноситься. Строки будут переноситься по значению min(editor.wrappingColumn, viewportWidthInColumns).
    "editor.wordWrap": false,

    // Управляет отступом строк с переносом по словам. Допустимые значения: "none", "same" или "indent".
    "editor.wrappingIndent": "same",

    // Множитель, используемый для параметров deltaX и deltaY событий прокрутки колесика мыши.
    "editor.mouseWheelScrollSensitivity": 1,

    // Определяет, должны ли при вводе текста отображаться краткие предложения.
    "editor.quickSuggestions": true,

    // Управляет длительностью задержки (в мс), перед отображением кратких предложений.
    "editor.quickSuggestionsDelay": 10,

    // Включение подсказок для параметров
    "editor.parameterHints": true,

    // Определяет, должен ли редактор автоматически закрывать скобки после открытия.
    "editor.autoClosingBrackets": true,

    // Управляет параметром, определяющим, должен ли редактор автоматически форматировать строку после ввода.
    "editor.formatOnType": false,

    // Определяет, должны ли при вводе триггерных символов автоматически отображаться предложения.
    "editor.suggestOnTriggerCharacters": true,

    // Определяет, можно ли принимать предложения клавишей ВВОД в дополнение к клавише TAB. Это помогает избежать неоднозначности между вставкой новых строк или принятием предложений.
    "editor.acceptSuggestionOnEnter": true,

    // Управляет отображением фрагментов вместе с другими предложениями и их сортировкой.
    "editor.snippetSuggestions": "bottom",

    // Включите предложения на основе слов.
    "editor.wordBasedSuggestions": true,

    // Вставка фрагментов при совпадении их префиксов. Функция работает оптимально, если параметр "quickSuggestions" отключен.
    "editor.tabCompletion": false,

    // Определяет, будет ли редактор выделять фрагменты, совпадающие с выделенным текстом.
    "editor.selectionHighlight": true,

    // Определяет, сколько украшений могут отображаться на одном месте в обзорной линейке.
    "editor.overviewRulerLanes": 3,

    // Управляет стилем анимации курсора. Допустимые значения: "blink", "smooth", "phase", "expand" и "solid"
    "editor.cursorBlinking": "blink",

    // Изменение размера шрифта в редакторе при нажатой клавише CTRL и движении колесика мыши
    "editor.mouseWheelZoom": true,

    // Определяет стиль курсора. Допустимые значения: "block", "line" и "underline"
    "editor.cursorStyle": "line",

    // Включает лигатуры шрифта.
    "editor.fontLigatures": false,

    // Управляет скрытием курсора в обзорной линейке.
    "editor.hideCursorInOverviewRuler": false,

    // Определяет, должен ли редактор обрабатывать символы пробела; возможные значения: "none", "boundary" и "all". Параметр "boundary" не обрабатывает единичные пробелы между словами.
    "editor.renderWhitespace": "none",

    // Определяет, должны ли в редакторе отображаться управляющие символы.
    "editor.renderControlCharacters": false,

    // Определяет, должны ли в редакторе отображаться направляющие отступа.
    "editor.renderIndentGuides": false,

    // Определяет, должен ли редактор отображать текущее выделение строки
    "editor.renderLineHighlight": true,

    // Управляет показом групп связанных элементов кода в редакторе
    "editor.codeLens": true,

    // Определяет, включено ли сворачивание кода в редакторе.
    "editor.folding": true,

    // Вставка и удаление пробелов после позиции табуляции
    "editor.useTabStops": true,

    // Удалить автоматически вставляемый конечный пробел
    "editor.trimAutoWhitespace": true,

    // Оставлять просматривающие редакторы открытыми, даже если дважды щелкнуто их содержимое или нажата клавиша ESC.
    "editor.stablePeek": false,

    // Определяет, как редактор несовпадений отображает отличия: рядом или в тексте.
    "diffEditor.renderSideBySide": true,

    // Определяет, должен ли редактор несовпадений трактовать несовпадения символов-разделителей как различия.
    "diffEditor.ignoreTrimWhitespace": true,


// Emmet

    // Если включено, сокращения Emmet разворачиваются при нажатии клавиши TAB.
    "emmet.triggerExpansionOnTab": true,

    // Настройки, которые используются для изменения поведения некоторых действий и сопоставителей Emmet.
    "emmet.preferences": {},

    // Задайте профиль для указанного синтаксиса или используйте свой собственный профиль с определенными правилами.
    "emmet.syntaxProfiles": {},

    // Массив языков, в которых не должны развертываться сокращения Emmet.
    "emmet.excludeLanguages": [],


// Workbench

    // Определяет, должны ли открытые редакторы отображаться на вкладках или нет.
    "workbench.editor.showTabs": true,

    // Определяет, должны ли открытые редакторы отображаться со значком. Требует включить тему значков.
    "workbench.editor.showIcons": true,

    // Определяет, отображаются ли открытые редакторы в режиме предварительного просмотра. Редакторы с предварительным просмотром повторно используются до сохранения (например, с помощью двойного щелчка или изменения).
    "workbench.editor.enablePreview": true,

    // Определяет, отображаются ли редакторы из Quick Open в режиме предварительного просмотра. Редакторы в режиме предварительного просмотра повторно используются до сохранения (например, с помощью двойного щелчка или изменения).
    "workbench.editor.enablePreviewFromQuickOpen": true,

    // Определяет место открытия редакторов. Выберите "Слева" или "Справа", чтобы открывать редакторы слева или справа от активного сейчас редактора. Выберите "Первый" или "Последний", чтобы открывать редакторы независимо от активного сейчас редактора.
    "workbench.editor.openPositioning": "right",

    // Управляет автоматическим закрытием Quick Open при потере фокуса.
    "workbench.quickOpen.closeOnFocusLost": true,

    // Управляет открытием редактора с отображением всех настроек по умолчанию при открытии настроек.
    "workbench.settings.openDefaultSettings": true,


// Окно

    // Если этот параметр включен, файлы будут открываться в новом окне, а не в существующем экземпляре.
    "window.openFilesInNewWindow": true,

    // Управляет повторным открытием папок после перезапуска. Выберите значение "none", чтобы не открывать папку повторно, "one", чтобы открывалась последняя папка, с которой вы работали, или "all", чтобы открывались все папки последнего сеанса.
    "window.reopenFolders": "one",

    // Определяет, должно ли окно восстанавливаться в полноэкранном режиме, если оно было закрыто в полноэкранном режиме.
    "window.restoreFullscreen": false,

    // Настройте масштаб окна. Исходный размер равен 0. Увеличение или уменьшение значения на 1 означает увеличение или уменьшение окна на 20 %. Чтобы более точно задать масштаб, можно также ввести десятичное число.
    "window.zoomLevel": 0,


// Файлы

    // Настройка стандартных масок для исключения файлов и папок.
    "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/.DS_Store": true
    },

    // Настройте сопоставления файлов с языками (например, "*.extension": "html"). У них будет приоритет перед заданными по умолчанию сопоставлениями установленных языков.
    "files.associations": {},

    // Кодировка набора символов по умолчанию, используемая при чтении и записи файлов
    "files.encoding": "utf8",

    // Символ конца строки по умолчанию.
    "files.eol": "\r\n",

    // Если этот параметр включен, при сохранении файла будут удалены завершающие символы-разделители.
    "files.trimTrailingWhitespace": false,

    // Управляет автоматическим сохранением измененных файлов. Допустимые значения: "off", "afterDelay", "onFocusChange" (редактор теряет фокус) и "onWindowChange" (окно теряет фокус). Если задано значение "afterDelay", можно настроить задержку в "files.autoSaveDelay".
    "files.autoSave": "afterDelay",

    // Определяет задержку в мс, после которой измененный файл сохраняется автоматически. Действует, только если параметр files.autoSave имеет значение "afterDelay".
    "files.autoSaveDelay": 1000,

    // Настройте стандартные маски путей файлов, чтобы исключить их из списка отслеживаемых файлов. После изменения этого параметра потребуется перезагрузка. При отображении сообщения "Код потребляет большое количество процессорного времени при запуске" вы можете исключить большие папки, чтобы уменьшить первоначальную загрузку.
    "files.watcherExclude": {
        "**/.git/objects/**": true
    },

    // Форматирование файла при сохранении. Модуль форматирования должен быть доступен, файл не должен сохраняться автоматически, а работа редактора не должна завершаться.
    "editor.formatOnSave": false,


// Проводник

    // Число редакторов, отображаемых на панели открытых редакторов. Задайте значение 0, чтобы скрыть панель.
    "explorer.openEditors.visible": 9,

    // Определяет, будет ли высота раздела открытых редакторов динамически адаптироваться к количеству элементов.
    "explorer.openEditors.dynamicHeight": true,

    // Определяет, следует ли обозревателю автоматически отображать файлы при их открытии.
    "explorer.autoReveal": true,

    // Определяет, разрешено ли перемещение файлов и папок перетаскиванием в проводнике.
    "explorer.enableDragAndDrop": true,


// Поиск

    // Настройте стандартные маски для исключения файлов и папок при поиске. Все стандартные маски наследуются от параметра file.exclude.
    "search.exclude": {
        "**/node_modules": true,
        "**/bower_components": true
    },

    // Настройте для включения результатов поиска глобальных символов в файлы по запросу для Quick Open.
    "search.quickOpen.includeSymbols": false,


// Обновить

    // Настройте канал обновления, по которому вы будете получать обновления. После изменения значения необходим перезапуск.
    "update.channel": "default",


// Git

    // С поддержкой GIT
    "git.enabled": true,

    // Путь к исполняемому файлу GIT
    "git.path": null,

    // Включено ли автоматическое обновление
    "git.autorefresh": true,

    // Включено ли автоматическое получение.
    "git.autofetch": true,

    // Следует ли предупреждать о длинных сообщениях о фиксации.
    "git.enableLongCommitWarning": true,

    // Всегда разрешать Code управлять большими репозиториями.
    "git.allowLargeRepositories": false,

    // Подтвердите синхронизацию репозиториев Git.
    "git.confirmSync": false,

    // Управляет счетчиком эмблем Git.
    "git.countBadge": "all",


// HTTP

    // Используемый параметр прокси. Если он не задан, он будет взят из переменных среды http_proxy и https_proxy.
    "http.proxy": "",

    // Должен ли сертификат прокси-сервера проверяться по списку предоставленных ЦС.
    "http.proxyStrictSSL": true,

    // Значение, отправляемое как заголовок "Proxy-Authorization" для каждого сетевого запроса.
    "http.proxyAuthorization": null,


// CSS

    // Controls CSS validation and problem severities.

    // Enables or disables all validations
    "css.validate": true,

    // When using a vendor-specific prefix make sure to also include all other vendor-specific properties
    "css.lint.compatibleVendorPrefixes": "ignore",

    // When using a vendor-specific prefix also include the standard property
    "css.lint.vendorPrefix": "warning",

    // Do not use duplicate style definitions
    "css.lint.duplicateProperties": "ignore",

    // Do not use empty rulesets
    "css.lint.emptyRules": "warning",

    // Import statements do not load in parallel
    "css.lint.importStatement": "ignore",

    // Do not use width or height when using padding or border
    "css.lint.boxModel": "ignore",

    // The universal selector (*) is known to be slow
    "css.lint.universalSelector": "ignore",

    // No unit for zero needed
    "css.lint.zeroUnits": "ignore",

    // @font-face rule must define 'src' and 'font-family' properties
    "css.lint.fontFaceProperties": "warning",

    // Hex colors must consist of three or six hex numbers
    "css.lint.hexColorLength": "error",

    // Invalid number of parameters
    "css.lint.argumentsInColorFunction": "error",

    // Unknown property.
    "css.lint.unknownProperties": "warning",

    // IE hacks are only necessary when supporting IE7 and older
    "css.lint.ieHack": "ignore",

    // Unknown vendor specific property.
    "css.lint.unknownVendorSpecificProperties": "ignore",

    // Property is ignored due to the display. E.g. with 'display: inline', the width, height, margin-top, margin-bottom, and float properties have no effect
    "css.lint.propertyIgnoredDueToDisplay": "warning",

    // Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.
    "css.lint.important": "ignore",

    // Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes.
    "css.lint.float": "ignore",

    // Selectors should not contain IDs because these rules are too tightly coupled with the HTML.
    "css.lint.idSelector": "ignore",


// SCSS (Sass)

    // Controls SCSS validation and problem severities.

    // Enables or disables all validations
    "scss.validate": true,

    // When using a vendor-specific prefix make sure to also include all other vendor-specific properties
    "scss.lint.compatibleVendorPrefixes": "ignore",

    // When using a vendor-specific prefix also include the standard property
    "scss.lint.vendorPrefix": "warning",

    // Do not use duplicate style definitions
    "scss.lint.duplicateProperties": "ignore",

    // Do not use empty rulesets
    "scss.lint.emptyRules": "warning",

    // Import statements do not load in parallel
    "scss.lint.importStatement": "ignore",

    // Do not use width or height when using padding or border
    "scss.lint.boxModel": "ignore",

    // The universal selector (*) is known to be slow
    "scss.lint.universalSelector": "ignore",

    // No unit for zero needed
    "scss.lint.zeroUnits": "ignore",

    // @font-face rule must define 'src' and 'font-family' properties
    "scss.lint.fontFaceProperties": "warning",

    // Hex colors must consist of three or six hex numbers
    "scss.lint.hexColorLength": "error",

    // Invalid number of parameters
    "scss.lint.argumentsInColorFunction": "error",

    // Unknown property.
    "scss.lint.unknownProperties": "warning",

    // IE hacks are only necessary when supporting IE7 and older
    "scss.lint.ieHack": "ignore",

    // Unknown vendor specific property.
    "scss.lint.unknownVendorSpecificProperties": "ignore",

    // Property is ignored due to the display. E.g. with 'display: inline', the width, height, margin-top, margin-bottom, and float properties have no effect
    "scss.lint.propertyIgnoredDueToDisplay": "warning",

    // Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.
    "scss.lint.important": "ignore",

    // Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes.
    "scss.lint.float": "ignore",

    // Selectors should not contain IDs because these rules are too tightly coupled with the HTML.
    "scss.lint.idSelector": "ignore",


// LESS

    // Controls LESS validation and problem severities.

    // Enables or disables all validations
    "less.validate": true,

    // When using a vendor-specific prefix make sure to also include all other vendor-specific properties
    "less.lint.compatibleVendorPrefixes": "ignore",

    // When using a vendor-specific prefix also include the standard property
    "less.lint.vendorPrefix": "warning",

    // Do not use duplicate style definitions
    "less.lint.duplicateProperties": "ignore",

    // Do not use empty rulesets
    "less.lint.emptyRules": "warning",

    // Import statements do not load in parallel
    "less.lint.importStatement": "ignore",

    // Do not use width or height when using padding or border
    "less.lint.boxModel": "ignore",

    // The universal selector (*) is known to be slow
    "less.lint.universalSelector": "ignore",

    // No unit for zero needed
    "less.lint.zeroUnits": "ignore",

    // @font-face rule must define 'src' and 'font-family' properties
    "less.lint.fontFaceProperties": "warning",

    // Hex colors must consist of three or six hex numbers
    "less.lint.hexColorLength": "error",

    // Invalid number of parameters
    "less.lint.argumentsInColorFunction": "error",

    // Unknown property.
    "less.lint.unknownProperties": "warning",

    // IE hacks are only necessary when supporting IE7 and older
    "less.lint.ieHack": "ignore",

    // Unknown vendor specific property.
    "less.lint.unknownVendorSpecificProperties": "ignore",

    // Property is ignored due to the display. E.g. with 'display: inline', the width, height, margin-top, margin-bottom, and float properties have no effect
    "less.lint.propertyIgnoredDueToDisplay": "warning",

    // Avoid using !important. It is an indication that the specificity of the entire CSS has gotten out of control and needs to be refactored.
    "less.lint.important": "ignore",

    // Avoid using 'float'. Floats lead to fragile CSS that is easy to break if one aspect of the layout changes.
    "less.lint.float": "ignore",

    // Selectors should not contain IDs because these rules are too tightly coupled with the HTML.
    "less.lint.idSelector": "ignore",


// HTML

    // Maximum amount of characters per line (0 = disable).
    "html.format.wrapLineLength": 120,

    // List of tags, comma separated, that shouldn't be reformatted. 'null' defaults to all tags listed at https://www.w3.org/TR/html5/dom.html#phrasing-content.
    "html.format.unformatted": "a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, script, select, small, span, strong, sub, sup, textarea, tt, var",

    // Indent and sections.
    "html.format.indentInnerHtml": false,

    // Whether existing line breaks before elements should be preserved. Only works before elements, not inside tags or for text.
    "html.format.preserveNewLines": true,

    // Maximum number of line breaks to be preserved in one chunk. Use 'null' for unlimited.
    "html.format.maxPreserveNewLines": null,

    // Format and indent {{#foo}} and {{/foo}}.
    "html.format.indentHandlebars": false,

    // End with a newline.
    "html.format.endWithNewline": false,

    // List of tags, comma separated, that should have an extra newline before them. 'null' defaults to "head, body, /html".
    "html.format.extraLiners": "head, body, /html",

    // Configures if the built-in HTML language support suggests Angular V1 tags and properties.
    "html.suggest.angular1": true,

    // Configures if the built-in HTML language support suggests Ionic tags, properties and values.
    "html.suggest.ionic": true,

    // Configures if the built-in HTML language support suggests HTML5 tags, properties and values.
    "html.suggest.html5": true,


// JSON

    // Associate schemas to JSON files in the current project
    "json.schemas": [],


// Markdown

    // A list of URLs or local paths to CSS style sheets to use from the markdown preview. Relative paths are interpreted relative to the folder open in the explorer. If there is no open folder, they are interpreted relative to the location of the markdown file. All '\' need to be written as '\\'.
    "markdown.styles": [],


// PHP

    // Включена ли проверка PHP.
    "php.validate.enable": true,

    // Указывает на исполняемый файл PHP.
    "php.validate.executablePath": null,

    // Запускается ли Linter при сохранении или в типе.
    "php.validate.run": "onSave",


// TypeScript

    // Указывает путь к папке, содержащей файлы tsserver и lib*.d.ts, которые необходимо использовать.
    "typescript.tsdk": null,

    // Проверка наличия версии TypeScript в рабочей области
    "typescript.check.workspaceVersion": true,

    // Проверка отличия компилятора TypeScript глобальной установки (например, tsc) от используемой языковой службы TypeScript.
    "typescript.check.tscVersion": true,

    // Включение трассировки сообщений, отправленных на сервер TS
    "typescript.tsserver.trace": "off",

    // Дополните функции сигнатурами их параметров.
    "typescript.useCodeSnippetsOnMethodSuggest": false,

    // Включить или отключить проверку TypeScript
    "typescript.validate.enable": true,

    // Определяет метод обработки пробелов после разделителя-запятой
    "typescript.format.insertSpaceAfterCommaDelimiter": true,

    //  Определяет метод обработки пробелов после точки с запятой в операторе for
    "typescript.format.insertSpaceAfterSemicolonInForStatements": true,

    // Определяет метод обработки пробелов после двоичного оператора
    "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": true,

    // Определяет метод обработки пробелов после ключевых слов в операторе потока управления
    "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true,

    // Определяет метод обработки пробелов после ключевого слова анонимной функции
    "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,

    // Определяет метод обработки пробелов после открытия и до закрытия непустых круглых скобок
    "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,

    // Определяет метод обработки пробелов после открытия и до закрытия непустых квадратных скобок
    "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,

    // Определяет, помещается ли открывающая фигурная скобка в новую строку для функций
    "typescript.format.placeOpenBraceOnNewLineForFunctions": false,

    // Определяет, помещается ли открывающая фигурная скобка в новую строку для управляющих блоков
    "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false,

    // Включить или отключить проверку JavaScript
    "javascript.validate.enable": true,

    // Определяет метод обработки пробелов после разделителя-запятой
    "javascript.format.insertSpaceAfterCommaDelimiter": true,

    //  Определяет метод обработки пробелов после точки с запятой в операторе for
    "javascript.format.insertSpaceAfterSemicolonInForStatements": true,

    // Определяет метод обработки пробелов после двоичного оператора
    "javascript.format.insertSpaceBeforeAndAfterBinaryOperators": true,

    // Определяет метод обработки пробелов после ключевых слов в операторе потока управления
    "javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": true,

    // Определяет метод обработки пробелов после ключевого слова анонимной функции
    "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,

    // Определяет метод обработки пробелов после открытия и до закрытия непустых круглых скобок
    "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,

    // Определяет метод обработки пробелов после открытия и до закрытия непустых квадратных скобок
    "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,

    // Определяет, помещается ли открывающая фигурная скобка в новую строку для функций
    "javascript.format.placeOpenBraceOnNewLineForFunctions": false,

    // Определяет, помещается ли открывающая фигурная скобка в новую строку для управляющих блоков
    "javascript.format.placeOpenBraceOnNewLineForControlBlocks": false,


// Расширения

    // Автоматически обновлять расширения
    "extensions.autoUpdate": false,


// Внешний терминал

    // Настройка терминала, который будет запущен в Windows.
    "terminal.external.windowsExec": "%COMSPEC%",

    // Настройка приложения терминала для запуска в OS X.
    "terminal.external.osxExec": "Terminal.app",

    // Настройка терминала для запуска в Linux.
    "terminal.external.linuxExec": "xterm",


// Интегрированный терминал

    // Путь оболочки, который используется терминалом в Linux.
    "terminal.integrated.shell.linux": "bash",

    // Аргументы командной строки, которые следует использовать в терминале Linux.
    "terminal.integrated.shellArgs.linux": [],

    // Путь оболочки, который используется терминалом в OS X.
    "terminal.integrated.shell.osx": "sh",

    // Аргументы командной строки, которые следует использовать в терминале OS X.
    "terminal.integrated.shellArgs.osx": [],

    // Путь оболочки, который используется терминалом в Windows. При работе с оболочкой, поставляемой с Windows (cmd, PowerShell или Bash на Ubuntu), укажите C:Windowssysnative вместо C:WindowsSystem32 для использования 64-разрядных версий.
    "terminal.integrated.shell.windows": "C:\\WINDOWS\\system32\\cmd.exe",

    // Определяет семейство шрифтов терминала, значение по умолчанию — editor.fontFamily.
    "terminal.integrated.fontFamily": "",

    // Определяет, будут ли включены лигатуры шрифтов для терминала.
    "terminal.integrated.fontLigatures": false,

    // Определяет размер шрифта (в пикселях) для терминала; значение по умолчанию — editor.fontSize.
    "terminal.integrated.fontSize": 10,

    // Определяет высоту строки терминала; это число умножается на размер шрифта терминала, что дает фактическую высоту строки в пикселях.
    "terminal.integrated.lineHeight": 1.2,

    // Управляет миганием курсора терминала.
    "terminal.integrated.cursorBlinking": false,

    // Управляет заданием переменных при запуске терминала, значение по умолчанию: "True" для OS X и "False" для других платформ.
    "terminal.integrated.setLocaleVariables": false,

    // Набор идентификаторов команд, настраиваемые сочетания клавиш которых не будут передаваться в оболочку, а вместо этого будут всегда обрабатываться Code. Это позволяет использовать настраиваемые сочетания клавиш, которые при обычных условиях были бы использованы оболочкой и работали бы так же, как если бы терминал не имел фокуса, например клавиши CTRL+P запускали бы Quick Open.
    "terminal.integrated.commandsToSkipShell": [
        "editor.action.toggleTabFocusMode",
        "workbench.action.quickOpen",
        "workbench.action.showCommands",
        "workbench.action.terminal.clear",
        "workbench.action.terminal.copySelection",
        "workbench.action.terminal.focus",
        "workbench.action.terminal.focusNext",
        "workbench.action.terminal.focusPrevious",
        "workbench.action.terminal.kill",
        "workbench.action.terminal.new",
        "workbench.action.terminal.paste",
        "workbench.action.terminal.runSelectedText",
        "workbench.action.terminal.scrollDown",
        "workbench.action.terminal.scrollDownPage",
        "workbench.action.terminal.scrollUp",
        "workbench.action.terminal.scrollUpPage",
        "workbench.action.terminal.toggleTerminal"
    ],

// Представление "Проблемы"

    // Определяет, следует ли представлению "Проблемы" отображать файлы при их открытии
    "problems.autoReveal": true,

// Телеметрия

    // Разрешить отправку сведений об использовании и ошибках в корпорацию Майкрософт.
    "telemetry.enableTelemetry": true,

    // Разрешить отправку отчетов о сбоях в корпорацию Майкрософт.
	// Чтобы этот параметр вступил в силу, требуется перезагрузка.
    "telemetry.enableCrashReporter": true
}

Проверка кода перед отправкой

        
cargo fmt --all -- --check
cargo +nightly fmt --all -- --check --unstable-features
cargo clippy -- -D warnings
cargo test --features runtime-benchmarks -p node-minterest-runtime benchmarking
cargo check
cargo audit --json

Проверка кода перед git push

Проверка кода перед отправкой

cargo fmt --all -- --check
cargo fmt --all -- --check --color always 2>&1 | grep Diff -A 20| head -20

Пропустить форматирования кода

// skip auto formatting
#[rustfmt::skip]

Правила компиляции

rust-analyzer.github.io/manual


//! Докуметация уровня модуля и линтер не будет "ругаться".

#![deny(
    missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
    trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
    unused_qualifications
)]

fn main(){
    print!("hi");
}

Коллекция линтов для выявления распространенных ошибок и улучшения кода Clippy выводит предупреждения и советы, но сам код не изменяет. Вы можете использовать Clippy для обнаружения потенциальных проблем в вашем коде, таких как неэффективные конструкции, ошибки производительности или стиль кода, но исправления нужно вносить вручную на основе полученных рекомендаций.

Запуск

$ cargo clippy -- -D warnings

Запуск в папке example

$ cargo clippy -p example

Clippy выдает предупреждения об использовании Rust по различным категориям:

  • Correctness (Корректность): предупреждает о распространенных ошибках программирования.
  • Idiom: Предупреждает о конструкциях кода, которые не совсем соответствуют стандартному стилю Rust.
  • Concision (Краткость): указывает на более компактные варианты кода.
  • Performance (Производительность): предлагает альтернативы, позволяющие избежать ненужной обработки или распределения.
  • Readability (Удобочитаемость): описывает изменения в коде, которые облегчат его чтение и понимание людьми.

clippy Lints in file lib.rs

rtc-stats-native/src/lib.rs

clippy Lints
#![doc = include_str!("../README.md")]
#![deny(
    macro_use_extern_crate,
    nonstandard_style,
    rust_2018_idioms,
    rustdoc::all,
    trivial_numeric_casts
)]
#![forbid(non_ascii_idents)]
#![warn(
    clippy::absolute_paths,
    clippy::as_conversions,
    clippy::as_ptr_cast_mut,
    clippy::assertions_on_result_states,
    clippy::branches_sharing_code,
    clippy::clear_with_drain,
    clippy::clone_on_ref_ptr,
    clippy::collection_is_never_read,
    clippy::create_dir,
    clippy::dbg_macro,
    clippy::debug_assert_with_mut_call,
    clippy::decimal_literal_representation,
    clippy::default_union_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::else_if_without_else,
    clippy::empty_drop,
    clippy::empty_line_after_outer_attr,
    clippy::empty_structs_with_brackets,
    clippy::equatable_if_let,
    clippy::empty_enum_variants_with_brackets,
    clippy::exit,
    clippy::expect_used,
    clippy::fallible_impl_from,
    clippy::filetype_is_file,
    clippy::float_cmp_const,
    clippy::fn_to_numeric_cast,
    clippy::fn_to_numeric_cast_any,
    clippy::format_push_string,
    clippy::get_unwrap,
    clippy::if_then_some_else_none,
    clippy::imprecise_flops,
    clippy::index_refutable_slice,
    clippy::infinite_loop,
    clippy::iter_on_empty_collections,
    clippy::iter_on_single_items,
    clippy::iter_over_hash_type,
    clippy::iter_with_drain,
    clippy::large_include_file,
    clippy::large_stack_frames,
    clippy::let_underscore_untyped,
    clippy::lossy_float_literal,
    clippy::manual_c_str_literals,
    clippy::manual_clamp,
    clippy::map_err_ignore,
    clippy::mem_forget,
    clippy::missing_assert_message,
    clippy::missing_asserts_for_indexing,
    clippy::missing_const_for_fn,
    clippy::missing_docs_in_private_items,
    clippy::multiple_inherent_impl,
    clippy::multiple_unsafe_ops_per_block,
    clippy::mutex_atomic,
    clippy::mutex_integer,
    clippy::needless_collect,
    clippy::needless_pass_by_ref_mut,
    clippy::needless_raw_strings,
    clippy::nonstandard_macro_braces,
    clippy::option_if_let_else,
    clippy::or_fun_call,
    clippy::panic_in_result_fn,
    clippy::partial_pub_fields,
    clippy::pedantic,
    clippy::print_stderr,
    clippy::print_stdout,
    clippy::pub_without_shorthand,
    clippy::ref_as_ptr,
    clippy::rc_buffer,
    clippy::rc_mutex,
    clippy::read_zero_byte_vec,
    clippy::readonly_write_lock,
    clippy::redundant_clone,
    clippy::redundant_type_annotations,
    clippy::ref_patterns,
    clippy::rest_pat_in_fully_bound_structs,
    clippy::same_name_method,
    clippy::semicolon_inside_block,
    clippy::shadow_unrelated,
    clippy::significant_drop_in_scrutinee,
    clippy::significant_drop_tightening,
    clippy::str_to_string,
    clippy::string_add,
    clippy::string_lit_as_bytes,
    clippy::string_lit_chars_any,
    clippy::string_slice,
    clippy::string_to_string,
    clippy::suboptimal_flops,
    clippy::suspicious_operation_groupings,
    clippy::suspicious_xor_used_as_pow,
    clippy::tests_outside_test_module,
    clippy::todo,
    clippy::trailing_empty_array,
    clippy::transmute_undefined_repr,
    clippy::trivial_regex,
    clippy::try_err,
    clippy::undocumented_unsafe_blocks,
    clippy::unimplemented,
    clippy::uninhabited_references,
    clippy::unnecessary_safety_comment,
    clippy::unnecessary_safety_doc,
    clippy::unnecessary_self_imports,
    clippy::unnecessary_struct_initialization,
    clippy::unneeded_field_pattern,
    clippy::unused_peekable,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    clippy::use_self,
    clippy::useless_let_if_seq,
    clippy::verbose_file_reads,
    clippy::wildcard_enum_match_arm,
    explicit_outlives_requirements,
    future_incompatible,
    let_underscore_drop,
    meta_variable_misuse,
    missing_abi,
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs,
    semicolon_in_expressions_from_macros,
    single_use_lifetimes,
    unit_bindings,
    unreachable_pub,
    unsafe_op_in_unsafe_fn,
    unstable_features,
    unused_crate_dependencies,
    unused_extern_crates,
    unused_import_braces,
    unused_lifetimes,
    unused_macro_rules,
    unused_qualifications,
    unused_results,
    variant_size_differences
)]
#![cfg_attr(feature = "mockable", allow(missing_docs))]
#![allow(
    clippy::module_name_repetitions,
    clippy::unimplemented,
    clippy::unnecessary_safety_comment,
    clippy::unnecessary_safety_doc,
    unreachable_pub
)]

.clippy.toml

See full lints list at

File .clippy.toml
# See full lints list at:
# https://rust-lang.github.io/rust-clippy/master/index.html

absolute-paths-allowed-crates = [
    "backoff",
    "fantoccini",
    "log",
    "proto",
    "reqwest",
    "syn",
    "time",
    "tonic",
    "web_sys",
]

doc-valid-idents = [
    "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
    "DirectX", "ECMAScript",
    "GPLv2", "GPLv3", "GitHub", "GitLab",
    "IPv4", "IPv6", "JavaScript", "NaN", "NaNs",
    "OAuth", "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", "TrueType",
    "iOS", "macOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW",
    "BigInt64Array", "BigUint64Array",
    "ConstrainDOMString", "ConstrainULong",
    "DisplayMediaStreamConstraints",
    "DOMHighResTimeStamp",
    "getDisplayMedia", "getUserMedia", "gRPC",
    "MediaDevices", "MediaDeviceKind", "MediaDeviceInfo",
    "MediaStream", "MediaStreamConstraints",
    "MediaStreamTrack", "MediaStreamTrackState",
    "MediaTrackConstraints",
    "MessageEvent",
    "RESTful",
    "RTCAudioSenderStats", "RTCSenderAudioTrackAttachmentStats",
    "RTCConfiguration",
    "RTCDataChannel",
    "RTCDtlsTransport",
    "RTCIceCandidate", "RTCIceCandidateInit", "RTCIceCandidateType",
    "RTCIceServer", "RTCIceTransport",
    "RTCPeerConnection", "RTCPeerConnectionIceEvent",
    "RTCRtpCodecCapability",
    "RTCRtpParameters",
    "RTCRtpSender", "RTCSenderVideoTrackAttachmentStats",
    "RTCRtpTransceiver", "RTCRtpTransceiverDirection",
    "RTCSctpTransport",
    "RTCSdpType",
    "RTCStats", "RTCStatsReport",
    "RTCTrackEvent",
    "RTCVideoSenderStats",
    "VideoFacingModeEnum",
    "WebAPI", "WebDriver", "WebRTC", "WebSocket",
]

standard-macro-braces = [
    { name = "assert", brace = "(" },
    { name = "assert_eq", brace = "(" },
    { name = "assert_ne", brace = "(" },
    { name = "debug_assert", brace = "(" },
    { name = "debug_assert_eq", brace = "(" },
    { name = "debug_assert_ne", brace = "(" },
    { name = "format", brace = "(" },
    { name = "format_args", brace = "(" },
    { name = "format_ident", brace = "(" },
    { name = "json", brace = "(" },
    { name = "matches", brace = "(" },
    { name = "panic", brace = "(" },
    { name = "parse_quote", brace = "{" },
    { name = "print", brace = "(" },
    { name = "println", brace = "(" },
    { name = "quote", brace = "{" },
    { name = "quote_spanned", brace = "{" },
    { name = "Token", brace = "[" },
    { name = "vec", brace = "[" },
    { name = "write", brace = "(" },
    { name = "writeln", brace = "(" },
]

Настройка проекта

File Cargo.toml:

[package.metadata.clippy]
config-file = "clippy.toml"
forbid = ["non_ascii_idents"]
warn = ["future_incompatible", "unused_crate_dependencies"]

File Makefile:

##################
# Cargo commands #
##################

# Resolve Cargo project dependencies.
#
# Usage:
#        make cargo [cmd=(<cargo-cmd>)]

all: cargo.fmt cargo.clippy

# Format Rust sources with rustfmt.
#
# Usage:
#        make cargo.fmt [check=(no|yes)]

cargo.fmt:
        cargo +nightly fmt --all $(if $(call eq,$(check),yes),-- --check,)

# Perform static code analysis with Clippy.
# Usage:
#        make cargo.clippy

cargo.clippy:
        cargo clippy --all-targets --all-features -- -D warnings


File src/_clippy_lints.rs:

#![deny(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]
//#![doc = include_str!("../README.md")]
#![deny(
    macro_use_extern_crate,
    nonstandard_style,
    rustdoc::all,
    trivial_numeric_casts
)]
 
#![warn(
    clippy::absolute_paths,
    .....
    variant_size_differences
)]
#![cfg_attr(feature = "mockable", allow(missing_docs))]
#![allow(
    clippy::module_name_repetitions,
    clippy::unimplemented,
    clippy::unnecessary_safety_comment,
    clippy::unnecessary_safety_doc,
    unreachable_pub
)]
// TODO: Remove on next `derive_more` major version.
#![allow(clippy::uninlined_format_args, clippy::use_debug)]

File .clippy.toml:

# See full lints list at:
# https://rust-lang.github.io/rust-clippy/master/index.html
 
standard-macro-braces = [
    { name = "assert", brace = "(" },
    { name = "assert_eq", brace = "(" },
    { name = "assert_ne", brace = "(" },
    { name = "debug_assert", brace = "(" },
    { name = "debug_assert_eq", brace = "(" },
    { name = "debug_assert_ne", brace = "(" },
    { name = "format", brace = "(" },
    { name = "format_args", brace = "(" },
    { name = "format_ident", brace = "(" },
    { name = "json", brace = "(" },
    { name = "matches", brace = "(" },
    { name = "panic", brace = "(" },
    { name = "parse_quote", brace = "{" },
    { name = "print", brace = "(" },
    { name = "println", brace = "(" },
    { name = "quote", brace = "{" },
    { name = "quote_spanned", brace = "{" },
    { name = "Token", brace = "[" },
    { name = "vec", brace = "[" },
    { name = "write", brace = "(" },
    { name = "writeln", brace = "(" },
]

File src/main.rs*:

//! Documentstion

/// linting module for clean code
mod _clippy_lints;
 
fn main() {
    println!("Hello, world!");
}

Add clippy lints to file src/_clippy_lints.rs
#![deny(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]
//#![doc = include_str!("../README.md")]
#![deny(
    macro_use_extern_crate,
    nonstandard_style,
    rustdoc::all,
    trivial_numeric_casts
)]
 
#![warn(
    clippy::absolute_paths,
    clippy::as_conversions,
    clippy::as_ptr_cast_mut,
    clippy::assertions_on_result_states,
    clippy::branches_sharing_code,
    clippy::clear_with_drain,
    clippy::clone_on_ref_ptr,
    clippy::collection_is_never_read,
    clippy::create_dir,
    clippy::dbg_macro,
    clippy::debug_assert_with_mut_call,
    clippy::decimal_literal_representation,
    clippy::default_union_representation,
    clippy::derive_partial_eq_without_eq,
    clippy::else_if_without_else,
    clippy::empty_drop,
    clippy::empty_line_after_outer_attr,
    clippy::empty_structs_with_brackets,
    clippy::equatable_if_let,
    clippy::empty_enum_variants_with_brackets,
    clippy::exit,
    clippy::expect_used,
    clippy::fallible_impl_from,
    clippy::filetype_is_file,
    clippy::float_cmp_const,
    clippy::fn_to_numeric_cast,
    clippy::fn_to_numeric_cast_any,
    clippy::format_push_string,
    clippy::get_unwrap,
    clippy::if_then_some_else_none,
    clippy::imprecise_flops,
    clippy::index_refutable_slice,
    clippy::infinite_loop,
    clippy::iter_on_empty_collections,
    clippy::iter_on_single_items,
    clippy::iter_over_hash_type,
    clippy::iter_with_drain,
    clippy::large_include_file,
    clippy::large_stack_frames,
    clippy::let_underscore_untyped,
    clippy::lossy_float_literal,
    clippy::manual_str_repeat,
    clippy::manual_clamp,
    clippy::map_err_ignore,
    clippy::mem_forget,
    clippy::missing_assert_message,
    clippy::missing_asserts_for_indexing,
    clippy::missing_const_for_fn,
    clippy::missing_docs_in_private_items,
    clippy::multiple_inherent_impl,
    clippy::multiple_unsafe_ops_per_block,
    clippy::mutex_atomic,
    clippy::mutex_integer,
    clippy::needless_collect,
    clippy::needless_pass_by_ref_mut,
    clippy::needless_raw_strings,
    clippy::nonstandard_macro_braces,
    clippy::option_if_let_else,
    clippy::or_fun_call,
    clippy::panic_in_result_fn,
    clippy::partial_pub_fields,
    clippy::pedantic,
    clippy::print_stderr,
    clippy::print_stdout,
    clippy::pub_without_shorthand,
    clippy::ptr_as_ptr,
    clippy::rc_buffer,
    clippy::rc_mutex,
    clippy::read_zero_byte_vec,
    clippy::readonly_write_lock,
    clippy::redundant_clone,
    clippy::redundant_type_annotations,
    clippy::ref_patterns,
    clippy::rest_pat_in_fully_bound_structs,
    clippy::same_name_method,
    clippy::semicolon_inside_block,
    clippy::shadow_unrelated,
    clippy::significant_drop_in_scrutinee,
    clippy::significant_drop_tightening,
    clippy::str_to_string,
    clippy::string_add,
    clippy::string_lit_as_bytes,
    clippy::string_lit_chars_any,
    clippy::string_slice,
    clippy::string_to_string,
    clippy::suboptimal_flops,
    clippy::suspicious_operation_groupings,
    clippy::suspicious_xor_used_as_pow,
    clippy::tests_outside_test_module,
    clippy::todo,
    clippy::trailing_empty_array,
    clippy::transmute_undefined_repr,
    clippy::trivial_regex,
    clippy::try_err,
    clippy::undocumented_unsafe_blocks,
    clippy::unimplemented,
    clippy::uninhabited_references,
    clippy::unnecessary_safety_comment,
    clippy::unnecessary_safety_doc,
    clippy::unnecessary_self_imports,
    clippy::unnecessary_struct_initialization,
    clippy::unneeded_field_pattern,
    clippy::unused_peekable,
    clippy::unwrap_in_result,
    clippy::unwrap_used,
    clippy::use_debug,
    clippy::use_self,
    clippy::useless_let_if_seq,
    clippy::verbose_file_reads,
    clippy::wildcard_enum_match_arm,
    explicit_outlives_requirements,
    let_underscore_drop,
    meta_variable_misuse,
    missing_abi,
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs,
    semicolon_in_expressions_from_macros,
    single_use_lifetimes,
    unit_bindings,
    unreachable_pub,
    unsafe_op_in_unsafe_fn,
    unstable_features,
    unused_extern_crates,
    unused_import_braces,
    unused_lifetimes,
    unused_macro_rules,
    unused_qualifications,
    unused_results,
    variant_size_differences
)]
#![cfg_attr(feature = "mockable", allow(missing_docs))]
#![allow(
    clippy::module_name_repetitions,
    clippy::unimplemented,
    clippy::unnecessary_safety_comment,
    clippy::unnecessary_safety_doc,
    unreachable_pub
)]
// TODO: Remove on next `derive_more` major version.
#![allow(clippy::uninlined_format_args, clippy::use_debug)]

Установка

Установка

$ rustup component add clippy
$ rustup component add clippy-preview

Настроить поведение некоторых линтов

Файл .clippy.toml

Файл .clippy.toml:

avoid-breaking-exported-api = false
disallowed-names = ["toto", "tata", "titi"]
cyclomatic-complexity-threshold = 30

Настройка в файлах

See full lints list at

#![deny(clippy::single_match, clippy::box_vec)]
#![allow(clippy::single_match, clippy::box_vec)]
#![warn(clippy::single_match, clippy::box_vec)]
#![forbid(clippy::single_match, clippy::box_vec)]

    clippy::all(все , что по умолчанию: все категории ниже , за исключением nursery, pedanticи cargo)
    clippy::correctness (код, который является просто неправильным или очень очень бесполезным, по умолчанию вызывает серьезные ошибки)
    clippy::style (код, который должен быть написан более идиоматическим способом)
    clippy::complexity (код, который делает что-то простое, но сложным образом)
    clippy::perf (код, который можно написать быстрее)
    clippy::pedantic (строчки довольно строгие, по умолчанию отключены)
    clippy::nursery (новые линты, которые еще не совсем готовы, по умолчанию отключены)
    clippy::cargo (проверка по грузовому манифесту, по умолчанию отключена)

Запустите Clippy

Запустите Clippy

    $ cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml

    $ cargo clippy
     # если вы хотите, чтобы при сборке предупреждений задание на сборку не выполнялось, используйте
    $ cargo clippy -- -D warnings
    # для того, чтобы также проверить тесты и функции ящиков не по умолчанию, используйте
    $ cargo clippy --all-targets --all-features -- -D warnings
    $ cargo test
    # автоматическое исправление
    $ cargo clippy --fix
    # запуск в папке example
    $ cargo clippy -p example
    # запуск в папке example без учета проверки зависимостей
    $ cargo clippy -p example -- --no-deps

Умалчивания Clippy линтов:

fn test(unix_millis:u64)->i64{
  i64::from(unix_millis)
}

#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
fn test(unix_millis:u64)->i64{
  unix_millis as i64
}

rustfmt

аналог clang-format

rustfmt/Configurations

rustfmt

# Установка

$ rustup component add rustfmt
$ rustup component add rustfmt --toolchain nightly

# Форматирование всех файлов
$ cargo fmt --all  
$ cargo fmt --all -- --check --color always 2>&1 | grep Diff -A 20| head -20
$ cargo +nightly fmt --all -- --check --unstable-features

# Вывод в stdout для предварительного просмотра
$ cargo +nightly fmt -- --emit stdout

# Форматирование отдельных файлов
$ cargo install rustfmt
$ rustfmt src/main.rs --check
$ rustfmt src/main.rs src/lib.rs
$ rustfmt --edition 2021 -- */*.rs

# Проверка вывода форматирования
$ echo "fn     main() {}" | rustfmt

--check покажет что будет форматировать

--all отформатируйте все пакеты, а также их локальные зависимости на основе пути

File .rustfmt.toml

# See full list at:
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md

max_width = 80
format_strings = false
imports_granularity = "Crate"
normalize_comments = true
wrap_comments = true

reorder_impl_items = true
use_try_shorthand = true

error_on_line_overflow = true
error_on_unformatted = true

unstable_features = true

rust-lang.github.io/rustfmt

Переопределить настройки по умолчанию в файле .rustfmt.toml

Файл .rustfmt.toml

Параметры по умолчанию вывести в файл rustfmt.toml
$ rustfmt --print-config default rustfmt.toml

Список всех параметров
$ rustfmt --help=config

max_width = 100 # Максимальная ширина каждой строки
hard_tabs = false # Использовать символы табуляции для отступа, пробелы для выравнивания
tab_spaces = 4 # Количество пробелов на вкладке
newline_style = 'Auto' # [Auto|Windows|Unix|Native] Окончания строк Unix или Windows
use_small_heuristics = 'Default' # [Off | Max | Default] Использовать ли другое форматирование для элементов и выражений, если они удовлетворяют эвристическому понятию 'small'
reorder_imports = true # Изменение порядка импорта и извлечения ящиков в алфавитном порядке
reorder_modules = true # Изменить порядок операторов в алфавитном порядке в группе
remove_nested_parens = true # Удалить вложенные парены
edition = '2015' # [2015 | 2018] Редакция парсера (RFC 2052)
merge_derives = true # Объединить несколько `#[derive(...)]` в один
use_try_shorthand = false # Заменить использование попытки! макрос по? стенография
use_field_init_shorthand = false # Использовать сокращение поля инициализации, если это возможно
force_explicit_abi = true # Всегда печатать abi для внешних элементов

Запрет форматирования rustfmt

#[rustfmt::skip]

Чтобы запретить rustfmt форматировать макрос или атрибут, используйте:

#[rustfmt::skip::macros(target_macro_name)] или 
#[rustfmt::skip::attributes(target_attribute_name)]

#![rustfmt::skip::attributes(custom_attribute)]

#[custom_attribute(formatting , here , should , be , Skipped)]
#[rustfmt::skip::macros(html)]
fn main() {
    let macro_result1 = html! { <div>Hello</div>}.to_string();
}

Пример

cucumber/.rustfmt.toml

# Project configuration for rustfmt Rust code formatter.
# See full list of configurations at:
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md

max_width = 80
format_strings = false
imports_granularity = "Crate"

format_code_in_doc_comments = true
format_macro_matchers = true
use_try_shorthand = true

error_on_line_overflow = true
error_on_unformatted = true

unstable_features = true

rust-analyzer — это библиотека для семантического анализа кода Rust по мере его изменения во времени.

Функции IntelliSense предоставляются языковым сервером Rust, rust-analyzer, предоставляющий подсказки для отображения предполагаемых типов, возвращаемых значений, описания, автозавершения, исправления ...

Возможно, вам потребуется установить набор инструментов GCC через build-essential

$ sudo apt-get install build-essential

rust-analyzer постоянно анализирует код и показывает лампочку 💡 в vscode, если может предложить исправление.

rust-analyzer — это “мозг” Rust для IDE. Он не компилятор, а языковой сервер (Language Server Protocol, LSP), который анализирует твой код в фоне, строит AST, типы, зависимости, референсы и предоставляет IDE функции вроде:

  • автодополнение (completion)
  • переход к определению
  • быстрые исправления (quick fix)
  • автоматические рефакторинги
  • подсказки по типам, doc, usages, и т.п.

Вот некоторые вещи, rust-analyzer которые являются просто тестами:

  • Форматирование кода (самое распространённое — не нужна лишняя куча YAML в CI, можно раскошелиться на форматер из теста).
  • Проверка отсутствия в истории коммитов слияний и обучение новых участников навыкам выживания в git.
  • Сбор руководства из специально отформатированных комментариев к документации по базе кода.
  • Проверка того, что база кода действительно достаточно хорошо документирована.
  • Обеспечение совместимости лицензий зависимостей.
  • Обеспечение линейности операций высокого уровня по размеру входных данных. Синтаксис — выделите синтетический файл размером 1, 2, 4, 8, 16 килобайт, запустите линейную регрессию, проверьте, чтобы результат выглядел как линия, а не парабола.

Настройки расширения

@ext:rust-lang.rust-analyzer

Глобальный файл ~/.config/Code/User/settings.json

Локальный файл .vscode/settings.json

{
    "editor.minimap.enabled": false,
    "window.zoomLevel": -1,
    "files.autoSave": "afterDelay",
  
    "rust-analyzer.cargo.allFeatures": true,
 
    "tabnine.experimentalAutoImports": true,
    "editor.codeActionsOnSave": {

    },
    "rust-analyzer.procMacro.ignored": {
         
    },
    "rust-analyzer.procMacro.enable": true, # поддержка derive-макросов (serde, async_trait, и др.)
    "rust-analyzer.procMacro.server": null,
    "debug.allowBreakpointsEverywhere": true,
    
    "rust-analyzer.inlayHints.bindingModeHints.enable": true,
    "editor.inlayHints.enabled": "on", # это показывает типы прямо в коде 
    "rust-analyzer.inlayHints.typeHints": true,
    "rust-analyzer.checkOnSave.command": "clippy", # анализирует код Clippy при сохранении
    "rust-analyzer.check.command": "check", # будет запускаться cargo clippy при сохранении файла
    "window.enableMenuBarMnemonics": false
}

${userHome} - путь к домашней папке пользователя
${workspaceFolder} - путь к папке, открытой в VS Code
${workspaceFolderBasename} — имя папки, открытой в VS Code, без косых черт (/)
${file} - текущий открытый файл
${fileWorkspaceFolder} - рабочая папка текущего открытого файла
${relativeFile} - текущий открытый файл относительноworkspaceFolder
${relativeFileDirname} - имя каталога текущего открытого файла относительноworkspaceFolder
${fileBasename} - базовое имя текущего открытого файла
${fileBasenameNoExtension} - базовое имя текущего открытого файла без расширения.
${fileExtname} - расширение текущего открытого файла
${fileDirname} - путь к папке с текущим открытым файлом
${fileDirnameBasename} - имя папки текущего открытого файла
${cwd} — текущий рабочий каталог исполнителя задач при запуске VS Code.
${lineNumber} - номер текущей выделенной строки в активном файле
${selectedText} - текущий выделенный текст в активном файле
${execPath} — путь к исполняемому файлу VS Code.
${defaultBuildTask} — имя задачи сборки по умолчанию.
${pathSeparator} — символ, используемый операционной системой для разделения компонентов в путях к файлам.

Навигация по коду

Функции навигации по коду доступны в контекстном меню редактора.

  • Перейти к определению F12 — перейти к исходному коду определения типа.
  • Peek Definition Ctrl+Shift+F10 — открыть окно Peek с определением типа.
  • Перейти к ссылкам Shift+F12 — показать все ссылки для типа.
  • Показать иерархию вызовов Shift+Alt+H — показать все вызовы от функции или к ней.

интеграция clippy в rust-analyzer

Линтер rustc, включенный по умолчанию, обнаруживает основные ошибки Rust, но вы можете использовать clippy, чтобы получить больше линтов. Чтобы включить интеграцию clippy в rust-analyzer, измените параметр Rust-analyzer > Check: Command ( rust-analyzer.check.command) на значение clippy по умолчанию check. Расширение rust-analyzer теперь будет запускаться cargo clippy при сохранении файла и отображать обрезанные предупреждения и ошибки непосредственно в редакторе и представлении «Проблемы»

Глобальный файл ~/.config/Code/User/settings.json:

{
    "rust-analyzer.check.command": "check",
}

cargo clone <crate> получить исходный код crate

cargo-clone

cargo install cargo-clone

cargo bloat что занимает большую часть места в вашем исполняемом файле.

cargo-bloat

cargo install cargo-bloat

% cargo bloat --release -n 10
Compiling ...
Analyzing target/release/cargo-bloat

 File  .text     Size       Crate Name
 0.9%   7.1%  27.0KiB cargo_bloat cargo_bloat::main
 0.8%   5.7%  21.4KiB cargo_bloat cargo_bloat::process_crate
 0.3%   2.3%   8.6KiB   [Unknown] read_line_info
 0.3%   2.1%   7.9KiB         std std::sys::unix::process::process_common::Command::capture_env
 0.3%   2.1%   7.8KiB        json json::parser::Parser::parse
 0.2%   1.7%   6.5KiB   [Unknown] elf_add
 0.2%   1.7%   6.3KiB         std __rdos_backtrace_dwarf_add
 0.2%   1.3%   5.0KiB         std <rustc_demangle::legacy::Demangle as core::fmt::Display>::fmt
 0.2%   1.3%   4.9KiB         std std::sys_common::backtrace::_print
 0.2%   1.3%   4.8KiB         std core::num::flt2dec::strategy::dragon::format_shortest
 9.8%  73.5% 278.0KiB             And 932 smaller methods. Use -n N to show more.
13.3% 100.0% 378.0KiB             .text section size, the file size is 2.8MiB

cargo profiler callgrind

подкоманда cargo для профилирования ваших приложений.

cargo-profiler

cargo install cargo-profiler

Дополнительные правила, не обрабатываемые Rustfmt и Clippy, описаны ниже.

Декларации импорта, реэкспорта и модулей Их следует разделить на следующие упорядоченные разделы:

  1. объявления модулей (mod и pub mode ключевые слова);

  2. импортирует разделы ( use ключевое слово):

    1. std/core импорт;
    2. импорт внешних ящиков;
    3. этот ящик импортирует (начинается с crate::);
    4. импорт из родительских модулей (начинается с super::);
    5. импорт из подмодулей (начинается с self::).
    6. реэкспорт разделов ( pub use ключевое слово):
    7. std/core реэкспорт;
  3. реэкспорт внешних ящиков;

    1. этот ящик реэкспортируется (начинается с crate::);
    2. реэкспорт из родительских модулей (начинается с super::);
    3. реэкспорт из подмодулей (начинается с self::).
  4. Пустая строка между этими разделами до и после обязательна.

Внутри каждого раздела и внутри каждого утверждения элементы должны быть отсортированы в алфавитном порядке.

Если импортированная черта не используется напрямую , ее необходимо подчеркнуть импортированную ( as _), чтобы не загрязнять пространство имен текущего модуля.

Импортируйте несколько элементов в одном операторе из одного места вместо использования нескольких операторов (обычно это контролируется merge_imports опцией Rustfmt ).

Правильный пример

//! Some module.

mod private_stuff;
pub mod public_stuff;

use std::sync::{Arc, Mutex};

use chrono::{DateTime, Utc};
use futures::Future as _;
use serde::{Deserialize, Serialize};

use crate::core::{DynFuture, DynStream};

use super::event;

use self::private_stuff::util;

pub use postgres::Type;

pub use crate::core::util::UnfoldingStream;

pub use super::props::Error;

pub use self::public_stuff::*;

const LIMIT: u8 = 100;

Неправильные примеры

Нет пустых строк:

//! Some module.
mod private_stuff;
pub mod public_stuff;

use std::sync::{Arc, Mutex};
use chrono::{DateTime, Utc};
use futures::Future as _;
use serde::{Deserialize, Serialize};
use crate::core::{DynFuture, DynStream};
use super::event;
use self::private_stuff::util;
pub use postgres::Type;
pub use crate::core::util::UnfoldingStream;
pub use super::props::Error;
pub use self::public_stuff::*;

use std::sync::{Arc, Mutex};
use chrono::{DateTime, Utc};
use futures::Future as _;
use serde::{Deserialize, Serialize};

use crate::core::{DynFuture, DynStream};
use super::event;
use self::private_stuff::util;

pub use postgres::Type;
pub use crate::core::util::UnfoldingStream;
pub use super::props::Error;
pub use self::public_stuff::*;

Атрибуты

Атрибуты объявлений должны быть отсортированы в алфавитном порядке. Элементы внутри атрибута также должны быть отсортированы в алфавитном порядке (так же, как они сортируются с помощью оператора Rustfmt Inside use).

✅ Правильный пример

#[allow(clippy::mut_mut)]
#[derive(smart_default::SmartDefault, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
struct User {
    #[serde(default)]
    id: u64,
}
```>


❌ Неправильные примеры

#[serde(deny_unknown_fields)] #[derive(smart_default::SmartDefault, Debug, Deserialize, Serialize)] #[allow(clippy::mut_mut)] struct User { id: u64, }


</div></td>
                <td id="cargo_c20cc58fde0417b9_other"><div class="cell-content" contenteditable="true"></div></td>
            </tr>   
            <tr id="cargo_a639db11c2b3eca3">
                <td id="cargo_a639db11c2b3eca3_topic"><div class="cell-content" contenteditable="true">

#### Утилита cargo-make

</div></td>
                <td id="cargo_a639db11c2b3eca3_content"><div class="cell-content" contenteditable="true">

cargo-make — это утилита для автоматизации задач в экосистеме Rust.
Она расширяет возможности стандартного Cargo, позволяя описывать и запускать сложные сценарии сборки, тестирования, деплоя и любых других действий через конфигурацию.
</div></td>
                <td id="cargo_a639db11c2b3eca3_other"><div class="cell-content" contenteditable="true"></div></td>
            </tr>   
            <tr id="cargo_65ef4111493fed9b">
                <td id="cargo_65ef4111493fed9b_topic"><div class="cell-content" contenteditable="true"></div></td>
                <td id="cargo_65ef4111493fed9b_content"><div class="cell-content" contenteditable="true">


`cargo-make` — это **утилита для автоматизации задач** в экосистеме Rust.
Она расширяет возможности стандартного Cargo, позволяя описывать и запускать сложные сценарии сборки, тестирования, деплоя и любых других действий через конфигурацию.


**Основные моменты**

* **Аналог Makefile**, но для Rust и в экосистеме Cargo.
* Работает через файл `Makefile.toml`, где ты описываешь задачи (tasks).
* Позволяет:

  * запускать последовательность команд (pipelines),
  * использовать условные шаги,
  * переопределять стандартные команды Cargo (`cargo build`, `cargo test` и т.д.),
  * интегрироваться с другими инструментами (docker, npm, bash-скрипты и пр.).

---

**Пример**

`Makefile.toml`:

```toml
[tasks.build-release]
command = "cargo"
args = ["build", "--release"]

[tasks.test-all]
command = "cargo"
args = ["test", "--all"]

[tasks.ci-flow]
dependencies = ["build-release", "test-all"]

Теперь можно вызвать:

cargo make ci-flow

и он выполнит сначала build-release, потом test-all.


Когда полезен

  • Если стандартного cargo build/test/run недостаточно.
  • Для CI/CD пайплайнов.
  • Для локальной автоматизации (генерация кода, линтинг, запуск бенчмарков и т.д.).
  • Чтобы не плодить bash-скрипты и Makefile, а держать всё в экосистеме Rust.