Rust
8.14K subscribers
415 photos
39 videos
3 files
963 links
Rust programming language

По всем вопросам- @textfaster

#VRHSZ
Download Telegram
👣 На Stepik обновили курс «Rust: полный курс разработчика. С нуля до профи»

Представьте: через три месяца вы открываете чужой Rust-код и читаете его как книгу.

Arc<Mutex<T>> не вызывает панику. impl Future не пугает. Вы точно знаете, почему компилятор ругается и как это починить за 10 секунд.

Это не фантазия. Это результат 50 уроков, в которых каждая концепция объясняется через код и закрепляется практикой.

Ownership, traits, generics, async, unsafe - всё, что казалось магией, станет рабочим инструментом.

А бонусом - портфолио проектов: от CLI-утилит до REST API и WebAssembly.

Вы и так знаете, что Rust - ваш следующий язык. Этот курс просто сделает это реальностью.

Сегодня - 55% процентов от цены, торопись: https://stepik.org/a/269250/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍104🖕4🔥3🥰1🌚1🤗1
👣 Rust Совет

MaybeUninit для ручной сборки структур без лишнего drop

Когда значение собирается по частям в unsafe-коде, FFI, парсере или аллокаторе, главная проблема не в самой инициализации. Главная проблема - что делать, если ошибка произошла посередине.

Например, одно поле структуры уже создано, а второе еще нет. В этот момент нельзя дропать всю структуру целиком: для Rust она еще не является полностью готовым объектом.

Правильный подход - явно помнить, какие поля уже инициализированы, и очищать только их. Для этого используют MaybeUninit, ptr::write, drop_in_place и, когда значение уже полностью готово, assume_init_drop.

MaybeUninit нужен не “чтобы обмануть Rust”, а чтобы аккуратно управлять жизненным циклом там, где компилятор уже не может сделать это за тебя.

Для таких случаев есть MaybeUninit:


use std::mem::MaybeUninit;

struct Buffer {
data: Vec<u8>,
meta: String,
}

let mut value = MaybeUninit::<Buffer>::uninit();

unsafe {
let ptr = value.as_mut_ptr();

std::ptr::addr_of_mut!((*ptr).data).write(vec![1, 2, 3]);

// Если дальше случилась ошибка,
// дропаем только уже инициализированное поле
std::ptr::addr_of_mut!((*ptr).data).drop_in_place();

// А всю Buffer не трогаем:
// meta еще не была создана
}


Более удобный вариант для полностью инициализированного MaybeUninit<T>:


let mut value = MaybeUninit::new(String::from("hello"));

unsafe {
value.assume_init_drop();
}


MaybeUninit<T> используют не просто для создания значения “без инициализации”. Он нужен, когда ты сам управляешь моментом, в который память становится настоящим T, и сам отвечаешь за корректный drop.

Если структура собирается по частям, компилятор уже не всегда может понять, какие поля реально созданы. Поэтому unsafe-логику лучше держать внутри маленькой функции или типа, а наружу отдавать обычный safe API. Так риск ошибок остается локальным и проверяемым.

#rust #rustlang #programming #unsafeRust
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥4🥰3🥴2👍1🤗1
Rust-эксперимент, который красиво объясняет, почему `Vec` почти всегда лучший варинт

Автор взял идею из Linux filesystem: inode хранит метаданные и указывает на блоки данных. Потом задал очень опасный, но полезный вопрос: а что если такую же схему перенести в Rust-контейнер?

Так появился PagedSmallVec: сначала маленький inline-буфер, потом данные раскладываются по фиксированным чанкам, а не лежат одним непрерывным куском памяти.

Звучит умно. На практике CPU быстро объясняет, кто здесь главный.

Обычный Vec почти всегда быстрее, потому что он делает ровно то, что любит процессор: данные лежат подряд, доступ предсказуемый, меньше переходов по указателям, меньше ветвлений, меньше cache misses. У PagedSmallVec каждый доступ после inline-части превращается в математику по чанкам: вычислить индекс чанка, offset, найти нужный блок, достать значение. Для u32 это особенно больно: там сама операция дешёвая, поэтому накладные расходы контейнера видны сразу.

Бенчмарки получились ожидаемые, но от этого не менее полезные: в обычных vector-like сценариях Vec чаще первый, SmallVec обычно второй, а paged-структура чаще третья. На push, pop, random indexing и ordered remove магии не случилось.

Когда обход сделали не через get(i) на каждый элемент, а чанками через for_each_chunk, структура стала выглядеть гораздо разумнее. Потому что её естественная единица работы - не отдельный элемент, а блок. И вот тут появляется главный урок: плохой API может убить даже неплохую идею, если заставляет структуру данных работать против своей природы.

Где такая схема может иметь смысл?

В append-heavy системах, где буфер часто растёт, но редко индексируется посередине. Например, логи, event buffers, tracing pipelines, ingestion queues. Там иногда важнее не копировать огромный непрерывный буфер при росте, чем выиграть каждый отдельный доступ.

Ещё один сценарий - chunk-native processing: стриминговая аналитика, batch transforms, сериализация, компрессия, обработка данных кусками. Если ваша логика работает чанками, а не элементами, paged layout уже не выглядит странным.

Если ваша цель - «сделать Vec, только быстрее», inode-style vector в Rust плохая идея.

Если цель - понять, где именно pointer-heavy layout проигрывает contiguous memory, как легко сломать инварианты через MaybeUninit, почему unsafe-контейнеры требуют железной дисциплины и почему API должен совпадать с layout, то эксперимент отличный.

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

https://sot.dev/inode-style-vector-in-rust.html
🔥109👍5🥰1💯1
32 тысячи звёзд на GitHub всего за 10 часов!

Терминал Warp открыли в open-source.

Это одна из самых заметных agentic development environment: терминалом уже пользуются больше 1 млн разработчиков по всему миру. Теперь проект хотят развивать быстрее за счёт комьюнити, внешних контрибьюторов и прозрачной разработки.

open-source-релиз стал возможен при поддержке OpenAI, которые выступили главным спонсором проекта.

Реакция комьюнити мощная: репозиторий за несколько часов собрал уже 30+ тысяч звёзд на GitHub.

И, конечно же, он написан на Rust.

https://github.com/warpdotdev/warp
28🔥13🥰4🤣4🤗2❤‍🔥1👍1
🧩 Новый язык программирования для AI-систем

Weft - это язык программирования, написанный на Rust, который упрощает создание AI-приложений, позволяя связывать LLM, людей и API без лишнего "проводки". Он предлагает визуальное представление программ и строгую типизацию, что делает разработку более интуитивной и безопасной.

🚀Основные моменты:
- Первоклассные взаимодействия с людьми через простые узлы.
- Возможность сворачивать группы узлов для упрощения структуры.
- Полная типизация, предотвращающая ошибки на этапе компиляции.
- Устойчивое выполнение программ, сохраняющих состояние после сбоев.
- Встроенные узлы для работы с различными сервисами и API.

📌 GitHub: https://github.com/WeaveMindAI/weft

#rust
💊25🤔11🔥5🖕3🥰21🤣1🤗1
👣 Как Rust обманывает процессор: тайная жизнь niche-оптимизации, drop flags и MIR


Большинство статей про Rust заканчиваются на borrow checker и lifetimes, как будто внутри компилятора живёт только проверяльщик заимствований и злой шрифтовый дизайнер для сообщений об ошибках. На деле там целый зоопарк механизмов, о которых редко пишут даже на конференциях. Я собрал несколько по настоящему любопытных вещей, которые меняют представление о том, как устроен язык изнутри, и подкрепил каждый сюжет кодом, который можно скопировать и проверить самому.

Начнём с того, чего никто не ждёт. Знакомая всем конструкция Option ссылки занимает ровно столько же байт, сколько и обычная ссылка. Это кажется магией: ведь у Option должен быть тег, отличающий Some от None. Никакого тега нет. Компилятор знает, что ссылка в Rust никогда не может быть нулевой, и использует нулевой адрес как представление варианта None. Этот трюк называется niche optimization, и он работает гораздо шире, чем принято думать.

Проверим руками: https://uproger.com/kak-rust-obmanyvaet-proczessor-tajnaya-zhizn-niche-optimizaczii-drop-flags-i-mir/
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥403🥰21🤗1
🔥 Продвинутый Rust без учебных игрушек

Базу уже прошли? Тогда следующий шаг - production-разработка.

На Stepik идет скидка 60% на продвинутый курс по Rust для тех, кто хочет не просто знать синтаксис, а строить реальные системы.

Внутри: async, unsafe, gRPC, lock-free, observability, Kafka, NATS, axum, tower, CI/CD и канареечный деплой.

Финальный проект - production-ready feed-сервис от архитектуры до релиза.

21 модуль, 84 урока, 400+ проверочных шагов.

Если хотите перейти от маленьких Rust-утилит к коммерческой разработке, сейчас хороший момент зайти: https://stepik.org/a/285608/pay
5👍5🔥4🥰1🤬1🤗1
🦀 Rust против C в embedded - не на словах, а в реальном тесте.

Исследователи взяли промышленное IoT-железо и запустили на нём две реализации одной и той же функциональности.

Одна команда писала на C.
Другая - на Rust.

Системы работали параллельно несколько месяцев в реальных условиях, а не в синтетическом бенчмарке.

Итог оказался неприятным для старого аргумента «для embedded нужен только C».

Rust не проиграл C ни по памяти, ни по скорости выполнения. Более того, runtime на Ariel OS оказался даже компактнее, чем классический bare-metal стек на C.

Вывод простой: аргумент «C быстрее и легче для прошивок» теперь звучит гораздо слабее.

Rust в embedded - это вполне рабочая альтернатива.

🔗 Подоробности: https://arxiv.org/abs/2604.25679

#Rust #RustLang #EmbeddedSystems #IoT #SystemsProgramming #C
🔥416🥰4🤔2🍓2😁1
📘 На платформе Mentorix вышел курс — «Rust для профессионалов»

Если вы уже знакомы с Rust и хотите углубить знания до уровня реального применения — этот курс даёт системное понимание и практику продвинутых возможностей языка.

В курсе:
• углублённая работа с памятью и моделью владения
• многопоточность и конкурентность
• продвинутые структуры и подходы
• написание производительных и надёжных систем
• практические задачи разного уровня сложности

Материал выстроен последовательно — от углубления базовых концепций к сложным сценариям использования.

Скидка 40% — действует 48 часов

👉 Пройти курс
🥴115🤬3😁2🥰1🤗1💊1
😁52🤣154👍4🔥3🥰1💯1
Как Rust обманывает процессор. Часть 2: niche сквозь крейты, dropck, Pin и провенанс указателей

В первой части мы коснулись niche-оптимизации, drop flags, MIR, Stacked Borrows и async-стейт-машин. Под статьёй справедливо заметили (спасибо, Mingun): про niche рассказано только в самой простой форме — Option<&T> и NonZeroU8.

А что происходит, когда enum живёт в одном крейте, оборачивается в newtype в другом, и оба варианта внешнего enum хранят один и тот же внутренний?

По факту у такого внешнего типа всего четыре состояния - байта должно хватить. Хватит ли?

Ответ короткий: иногда да, иногда нет, и причина не в теории, а в том, как rustc вообще считает layout. С этого и начнём.
https://uproger.com/kak-rust-obmanyvaet-proczessor-chast-2-niche-skvoz-krejty-dropck-pin-i-provenans-ukazatelej/
3🔥3👍1🥰1🤗1