1. 1. Introduction
  2. 2. Введение
  3. 3. C чего начать
  4. 4. Изучение Rust
    1. 4.1. Угадайка
    2. 4.2. Обедающие философы
    3. 4.3. Вызов кода на Rust из других языков
  5. 5. Синтаксис и семантика
    1. 5.1. Связывание имён
    2. 5.2. Функции
    3. 5.3. Простые типы
    4. 5.4. Комментарии
    5. 5.5. Конструкция `if`
    6. 5.6. Циклы
    7. 5.7. Владение
    8. 5.8. Ссылки и заимствование
    9. 5.9. Время жизни
    10. 5.10. Изменяемость
    11. 5.11. Структуры
    12. 5.12. Перечисления
    13. 5.13. Конструкция `match`
    14. 5.14. Шаблоны сопоставления `match`
    15. 5.15. Синтаксис методов
    16. 5.16. Вектора
    17. 5.17. Строки
    18. 5.18. Обобщённое программирование
    19. 5.19. Типажи
    20. 5.20. Типаж `Drop`
    21. 5.21. Конструкция `if let`
    22. 5.22. Типажи-объекты
    23. 5.23. Замыкания
    24. 5.24. Универсальный синтаксис вызова функций
    25. 5.25. Контейнеры и модули
    26. 5.26. `const` и `static`
    27. 5.27. Атрибуты
    28. 5.28. Псевдонимы типов
    29. 5.29. Приведение типов
    30. 5.30. Ассоциированные типы
    31. 5.31. Безразмерные типы
    32. 5.32. Перегрузка операций
    33. 5.33. Преобразования при разыменовании
    34. 5.34. Макросы
    35. 5.35. Сырые указатели
    36. 5.36. Небезопасный код
  6. 6. Эффективное использование Rust
    1. 6.1. Стек и куча
    2. 6.2. Тестирование
    3. 6.3. Условная компиляция
    4. 6.4. Документация
    5. 6.5. Итераторы
    6. 6.6. Многозадачность
    7. 6.7. Обработка ошибок
    8. 6.8. Выбор гарантий
    9. 6.9. Интерфейс внешних функций
    10. 6.10. Типажи `Borrow` и `AsRef`
    11. 6.11. Каналы сборок
    12. 6.12. Using Rust without the standard library
  7. 7. Нестабильные возможности Rust
    1. 7.1. Плагины к компилятору
    2. 7.2. Встроенный ассемблерный код
    3. 7.3. Без stdlib
    4. 7.4. Внутренние средства
    5. 7.5. Элементы языка
    6. 7.6. Продвинутое руководство по компоновке
    7. 7.7. Тесты производительности
    8. 7.8. Синтаксис упаковки и шаблоны `match`
    9. 7.9. Шаблоны `match` для срезов
    10. 7.10. Ассоциированные константы
    11. 7.11. Пользовательские менеджеры памяти
  8. 8. Глоссарий
  9. 9. Syntax Index
  10. 10. Библиография

Без stdlib

По умолчанию, std компонуется с каждым контейнером Rust. В некоторых случаях это нежелательно, и этого можно избежать с помощью атрибута #![no_std], примененного (привязанного) к контейнеру.

// a minimal library
#![crate_type="lib"]
#![feature(no_std)]
#![no_std]Run

Очевидно, должно быть нечто большее, чем просто библиотеки: #[no_std] можно использовать с исполняемыми контейнерами, а управлять точкой входа можно двумя способами: с помощью атрибута #[start], или с помощью переопределения прокладки (shim) для C функции main по умолчанию на вашу собственную.

В функцию, помеченную атрибутом #[start], передаются параметры командной строки в том же формате, что и в C:

#![feature(lang_items, start, no_std, libc)]
#![no_std]

// Pull in the system libc library for what crt0.o likely requires
extern crate libc;

// Entry point for this program
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    0
}

// These functions and traits are used by the compiler, but not
// for a bare-bones hello world. These are normally
// provided by libstd.
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }Run

Чтобы переопределить вставленную компилятором прокладку main, нужно сначала отключить ее с помощью #![no_main], а затем создать соответствующий символ с правильным ABI и правильным именем, что также потребует переопределение искажения (коверкания) имен компилятором (#[no_mangle]):

#![feature(no_std)]
#![no_std]
#![no_main]
#![feature(lang_items, start)]

extern crate libc;

#[no_mangle] // для уверенности в том, что этот символ будет называться `main` на выходе
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
    0
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }Run

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

Первая из этих трех функций, stack_exhausted, вызывается тогда, когда обнаруживается (происходит) переполнение стека. Эта функция имеет ряд ограничений, касающихся того, как она может быть вызвана и того, что она должна делать, но если регистр предела стека не поддерживается, то поток всегда имеет «бесконечный стек» и эта функция не должна быть вызвана (получить управление, срабатывать).

Вторая из этих трех функций, eh_personality, используется в механизме обработки ошибок компилятора. Она часто отображается на функцию personality (специализации) GCC (для получения дополнительной информации смотри реализацию libstd), но можно с уверенностью сказать, что для контейнеров, которые не вызывают панику, эта функция никогда не будет вызвана. Последняя функция, panic_fmt, также используются в механизме обработки ошибок компилятора.

Использование основной библиотеки (libcore)

Примечание: структура основной библиотеки (core) является нестабильной, и поэтому рекомендуется использовать стандартную библиотеку (std) там, где это возможно.

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

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

В качестве примера приведем программу, которая вычисляет скалярное произведение двух векторов, предоставленных из кода C, и использует идиоматические практики Rust.

#![feature(lang_items, start, no_std, core, libc)]
#![no_std]

extern crate core;

use core::prelude::*;

use core::mem;

#[no_mangle]
pub extern fn dot_product(a: *const u32, a_len: u32,
                          b: *const u32, b_len: u32) -> u32 {
    use core::raw::Slice;

    // Convert the provided arrays into Rust slices.
    // The core::raw module guarantees that the Slice
    // structure has the same memory layout as a &[T]
    // slice.
    //
    // This is an unsafe operation because the compiler
    // cannot tell the pointers are valid.
    let (a_slice, b_slice): (&[u32], &[u32]) = unsafe {
        mem::transmute((
            Slice { data: a, len: a_len as usize },
            Slice { data: b, len: b_len as usize },
        ))
    };

    // Iterate over the slices, collecting the result
    let mut ret = 0;
    for (i, j) in a_slice.iter().zip(b_slice.iter()) {
        ret += (*i) * (*j);
    }
    return ret;
}

#[lang = "panic_fmt"]
extern fn panic_fmt(args: &core::fmt::Arguments,
                    file: &str,
                    line: u32) -> ! {
    loop {}
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}Run

Обратите внимание, что здесь, в отличае от примеров, рассмотренных выше, есть один дополнительный lang элемент panic_fmt. Он должен быть определён потребителями libcore, потому что основная библиотека объявляет панику, но не определяет её. lang элемент panic_fmt определяет панику для этого контейнера, и необходимо гарантировать, что он никогда не возвращает значение.

Как видно в этом примере, основная библиотека предназначена для предоставления всей мощи Rust при любых обстоятельствах, независимо от требований платформы. Дополнительные библиотеки, такие как liballoc, добавляют функциональность для libcore, для работы которой нужно сделать некоторые платформо-зависимые предположения; но эти библиотеки всё равно более переносимы, чем стандартная библиотека в целом.