Блог*
#prog #rust #article Rust web frameworks have subpar error reporting Автор излагает свои требования к репорту и обработке ошибок (TL;DR: ошибки не должны теряться ни для клиента веб-сервера, ни для админа веб-сервера), показывает, как в этом отношении не…
#prog #rust #rustlib #article
biscotti, a new crate for HTTP cookies
Библиотека для работы с cookie. В статье-анонсе автор объясняет, почему он решил сделать новую библиотеку вместо того, чтобы использовать де-факто стандартную cookie.
* В отличие от cookie-rs, в biscotti используются разные типы для cookie запроса и cookie ответа сервера. В cookie-rs используются один и тот же тип, где у cookie от клиента все опциональные поля выставлены в None.
* biscotti поддерживает обработку нескольких cookie с одинаковыми именами в рамках одного запроса/ответа. В cookie-rs при обработке cookie с одинаковыми именами запоминаются только последняя информация, связанная с конкретным именем (иными словами, в cookie-rs map, в biscotti multimap).
* Централизованная обработка шифрования cookie и, как следствие, встроенная поддержка ротации ключей.
Разумеется, это не полная альтернатива: автор намеренно делал либу для сервера и потому biscotti не годится для работы с cookie на стороне клиента.
biscotti, a new crate for HTTP cookies
Библиотека для работы с cookie. В статье-анонсе автор объясняет, почему он решил сделать новую библиотеку вместо того, чтобы использовать де-факто стандартную cookie.
* В отличие от cookie-rs, в biscotti используются разные типы для cookie запроса и cookie ответа сервера. В cookie-rs используются один и тот же тип, где у cookie от клиента все опциональные поля выставлены в None.
* biscotti поддерживает обработку нескольких cookie с одинаковыми именами в рамках одного запроса/ответа. В cookie-rs при обработке cookie с одинаковыми именами запоминаются только последняя информация, связанная с конкретным именем (иными словами, в cookie-rs map, в biscotti multimap).
* Централизованная обработка шифрования cookie и, как следствие, встроенная поддержка ротации ключей.
Разумеется, это не полная альтернатива: автор намеренно делал либу для сервера и потому biscotti не годится для работы с cookie на стороне клиента.
Lpalmieri
biscotti, a new crate for HTTP cookies
Announcing the first release of `biscotti`, a new Rust library to handle HTTP cookies in servers.
🔥1
#prog #rust #rustlib #article
Getting meaningful stack traces from Rust tests returning a Result
TL;DR: конвертация в операторе
Великие умы мыслят одинаково, так что автор обнаружил, что на crates.io уже есть крейт testresult, который реализует идею. Тем не менее, там были возможности для улучшения, так что в итоге он сделал PR (главным образом — добавление
Getting meaningful stack traces from Rust tests returning a Result
TL;DR: конвертация в операторе
?
имеет возможность для настройки путём реализации From
/Into
для типа ошибки. Это можно использовать для того, чтобы сделать специальный тип ошибок, который паникует в реализации From::from
, а за счёт #[track_caller]
позволяет даже без бектрейса отловить место, где была создана ошибка.Великие умы мыслят одинаково, так что автор обнаружил, что на crates.io уже есть крейт testresult, который реализует идею. Тем не менее, там были возможности для улучшения, так что в итоге он сделал PR (главным образом — добавление
#[track_caller]
, но также и другие изменения для повышения полезности).Sylvain Wallez
Getting meaningful stack traces from Rust tests returning a Result
I was recently writing a test for a side project in Rust (more on that in a future post) and was frustrated by the lack of information reported when the test fails. I ended up with an interesting hack to report the precise location and error that caused a…
🥰3
#prog #rust #rustlib
coffee_break
Nowadays, the devious Rust compiler developers are trying to make the compiler even faster, and they're slowly succeeding.
Here comes Coffee break, a friendly developer tool to make this problem go away.
Before you run
coffee_break
Nowadays, the devious Rust compiler developers are trying to make the compiler even faster, and they're slowly succeeding.
Here comes Coffee break, a friendly developer tool to make this problem go away.
Before you run
cargo build
, reward yourself with a coffee break:use coffee_break::coffee_break;You just got 5 minutes to stretch your legs, get a coffee, or make Friday afternoon a bit nicer.
fn work_stuff() {
let maybe = |(true|false)||(false|true)||(true|false)|true;
let absolutely = maybe(true)(true)(true);
// Take a break and hit compile
coffee_break!(5 minutes);
}
👏7😁3
#prog #rust #rustlib
qualifier_attr — procedural macro attributes for adding "qualifiers" to various items.
qualifier_attr — procedural macro attributes for adding "qualifiers" to various items.
// We can add a qualifier to a function
// with an attribute.
#[qualifiers(const)]
fn const_fn() -> u32 {
42
}
const CONST_RES: u32 = const_fn();
// It's not so impressive on its own,
// but with `cfg_attr`, it can be conditional.
#[cfg_attr(
feature = "extern_c",
no_mangle,
qualifiers(pub, extern "C")
)]
fn extern_c_fn() -> u32 {
42
}
👍9
#prog #rust #rustlib
Стандартная библиотека Rust предоставляет типы Path и PathBuf, которые инкапсулируют в себе платформо-специфичные пути в файловой системе. Эти пути не обязательно закодированы в UTF-8, поэтому работать с
Подход std правилен в том смысле, что не делает каких-то предположений о содержимом файловых путей, но на практике подавляющее большинство путей и так в UTF-8, а некоторые программы вообще с не-UTF-8 путями не работают, поэтому такая педантичность мешается.
Библиотека camino позволяет сделать работу с путями более эргономичной. Именно, она предоставляет типы Utf8Path и Utf8PathBuf, которые повторяют функциональность
Если что, camino используется в rust-analyzer.
И ещё: если вам требуется отобразить путь при помощи
Стандартная библиотека Rust предоставляет типы Path и PathBuf, которые инкапсулируют в себе платформо-специфичные пути в файловой системе. Эти пути не обязательно закодированы в UTF-8, поэтому работать с
Path
не очень удобно: Path
не реализует Display
, множество полезных функций для манипуляции строками доступны только на str
, но конвертация из Path
в str
может вернуть ошибку.Подход std правилен в том смысле, что не делает каких-то предположений о содержимом файловых путей, но на практике подавляющее большинство путей и так в UTF-8, а некоторые программы вообще с не-UTF-8 путями не работают, поэтому такая педантичность мешается.
Библиотека camino позволяет сделать работу с путями более эргономичной. Именно, она предоставляет типы Utf8Path и Utf8PathBuf, которые повторяют функциональность
Path
и PathBuf
, но гарантированно в UTF-8. Эта проверка осуществляется только один раз: во время создания этих типов, поэтому преобразование из них в str
всегда успешно, и вдобавок они реализуют Display
.Если что, camino используется в rust-analyzer.
И ещё: если вам требуется отобразить путь при помощи
Display
, то вам пригодится метод display на Path
. Он возвращает тип, который по возможности отображает путь так же, как и str
, и каким-то образом замещает невалидные UTF-8 последовательности.👍15🤡5🔥1💩1
#prog #rust #rustlib
pre — библиотека для помощи с правильным использованием
Причина, по которой
Не смотря на то, что это лучше, чем ничего, это подход довольно хрупок. Помимо того, что не все используют clippy (и уж тем более никто не использует tidy вне разработки самого Rust), эти проверки недостаточно гранулярны: они проверяют лишь наличие комментариев но не их содержимое. Это означает, что если по каким-то причинам условия использования и их обоснования на месте вызова разъедутся, эти инструменты их не отловят. Ну и, разумеется, никакие линтеры by design не могут остановить компиляцию кода (если только не включить их в общий процесс сборки кода). Библиотека pre стремится заполнить этот пробел.
Именно, библиотека позволяет добавлять на
Эти условия трансформируются в дополнительный аргумент для функции — типа с нулевым размером — значение которого предоставляется на вызывающей стороне при помощи макроса
Подобный подход всё так же полагается на человека в плане непосредственно проверки условий, но за счёт проверки того, что каждое отдельное условие удовлетворено на вызывающей стороне с идентичной формулировкой позволяет синхронно развивать определение
Условия можно записывать не только словесно, но и также в виде предиката или специального синтаксиса для утверждения корректного выравнивания сырых указателей или их валидности для операций чтения и/или записи:
Также библиотека даёт способ предоставить предусловия для функций из сторонних библиотек.
К сожалению, на сегодняшний день у макросов имеется множество ограничений, которые в основном выражаются в их меньшей полезности на стабильной версии компилятора. Ну и, разумеется, автор советуют не использовать pre безусловно ввиду очевидного влияния на время компиляции и на потребительский код в случае использования pre в публичных интерфейсах.
pre — библиотека для помощи с правильным использованием
unsafe
кода.Причина, по которой
unsafe
может быть в публичном интерфейсе функции, заключается в том, что для корректной работы функции требуются условия, которые не могут быть проверены компилятором или которые проверять очень дорого. В среде разработки на Rust распространена культура использования safety comments. Именно, unsafe
функция перечисляет в документации необходимые условия для безопасного использования, а вызовы этой функции перечисляют причины, по которым условия удовлетворены. В clippy есть линт на отсутствующую safety документацию на unsafe
определениях, а в tidy (внутреннем линтере для компилятора Rust) есть даже проверка на наличие этих комментариев на вызывающей стороне.Не смотря на то, что это лучше, чем ничего, это подход довольно хрупок. Помимо того, что не все используют clippy (и уж тем более никто не использует tidy вне разработки самого Rust), эти проверки недостаточно гранулярны: они проверяют лишь наличие комментариев но не их содержимое. Это означает, что если по каким-то причинам условия использования и их обоснования на месте вызова разъедутся, эти инструменты их не отловят. Ну и, разумеется, никакие линтеры by design не могут остановить компиляцию кода (если только не включить их в общий процесс сборки кода). Библиотека pre стремится заполнить этот пробел.
Именно, библиотека позволяет добавлять на
unsafe
функции атрибуты #[pre]
, каждый из которых содержит одно условие — в простейшем виде просто в виде словесного описания:#[pre("`arg` is a meaningful value")]
fn foo(arg: i32) {
assert_eq!(arg, 42);
}
Эти условия трансформируются в дополнительный аргумент для функции — типа с нулевым размером — значение которого предоставляется на вызывающей стороне при помощи макроса
assures
:#[pre] // Enables `assure`ing preconditions inside the function
fn main() {
#[assure("`arg` is a meaningful value", reason = "42 is very meaningful")]
foo(42);
}
Подобный подход всё так же полагается на человека в плане непосредственно проверки условий, но за счёт проверки того, что каждое отдельное условие удовлетворено на вызывающей стороне с идентичной формулировкой позволяет синхронно развивать определение
unsafe
кода и его использование. Именно, за счёт того, что каждое условие становится частью аргумента, изменение списка условий (добавление, удаление или изменение формулировки) становится ошибкой компиляции.Условия можно записывать не только словесно, но и также в виде предиката или специального синтаксиса для утверждения корректного выравнивания сырых указателей или их валидности для операций чтения и/или записи:
#[pre(valid_ptr(ptr_name, r+w))]
fn foo(ptr_name: *mut i32) {}
#[pre(proper_align(ptr_name))]
fn bar(ptr_name: *mut i32) {}
// Предусловие в виде предиката также
// добавляет в функцию соответствующий
// `debug_assert!`
#[pre(a < b || b > 17)]
fn baz(a: i32, b: i32) {}
Также библиотека даёт способ предоставить предусловия для функций из сторонних библиотек.
К сожалению, на сегодняшний день у макросов имеется множество ограничений, которые в основном выражаются в их меньшей полезности на стабильной версии компилятора. Ну и, разумеется, автор советуют не использовать pre безусловно ввиду очевидного влияния на время компиляции и на потребительский код в случае использования pre в публичных интерфейсах.
docs.rs
pre - Rust
pre is a library to help programmers correctly uphold preconditions for function calls.
👍5🤔2
#prog #rust #rustlib #menacingopensource
Quickly prototype procedural macros using JavaScript or TypeScript!
crates.io/crates/js-macros
Quickly prototype procedural macros using JavaScript or TypeScript!
crates.io/crates/js-macros
👍5
#prog #rust #rustlib
Jiff — библиотека для работы с датой и временем от BurntSushi.
Jiff is a datetime library for Rust that encourages you to jump into the pit of success. The focus of this library is providing high level datetime primitives that are difficult to misuse and have reasonable performance.
Наиболее заметным отличием Jiff является возможность работать с разницей моментов не только в терминах абсолютных отрезков времени, но и в терминах календарных единиц (дни и месяцы, например). Также Jiff поддерживает арифметику дат с учётом прыжков во времени из-за daylight saving time.
Для того, чтобы определить, насколько Jiff подходит для ваших задач, советую почитать философию дизайна и сравнение с существующими библиотеками.
Jiff — библиотека для работы с датой и временем от BurntSushi.
Jiff is a datetime library for Rust that encourages you to jump into the pit of success. The focus of this library is providing high level datetime primitives that are difficult to misuse and have reasonable performance.
Наиболее заметным отличием Jiff является возможность работать с разницей моментов не только в терминах абсолютных отрезков времени, но и в терминах календарных единиц (дни и месяцы, например). Также Jiff поддерживает арифметику дат с учётом прыжков во времени из-за daylight saving time.
Для того, чтобы определить, насколько Jiff подходит для ваших задач, советую почитать философию дизайна и сравнение с существующими библиотеками.
👍3🔥2😐1
#prog #rust #rustlib
griddle — библиотека, которая реализует hash map с амортизированной по операциям вставки расширением размера. Может быть полезна для случаев, когда важна маленькая tail latency. Реализована не с нуля, а с помощью "сырого" API hashbrown.
На графике бенчмарк операций вставки для HashMap из std и griddle::HashMap.
griddle — библиотека, которая реализует hash map с амортизированной по операциям вставки расширением размера. Может быть полезна для случаев, когда важна маленькая tail latency. Реализована не с нуля, а с помощью "сырого" API hashbrown.
На графике бенчмарк операций вставки для HashMap из std и griddle::HashMap.
🔥7
#prog #rust #rustlib #article
Designing A Fast Concurrent Hash Table
Статья о дизайне papaya, многопоточной в основном lock-free хэш-мапы с упором на пропускную способность на операциях чтения из мапы и предсказуемые задержки (без пиков). Также пока что является, кажется, единственной подобной структурой данных, которую можно использовать из асинхронного кода.
Для того, чтобы избежать пиков задержки, использует инкрементальное изменение размера — и это одно из немногих мест, где используются блокировки.
Так как многопоточная мапа по определению не может иметь аналог entry API (по крайней мере, без кучи тонкостей из-за потенциальных гонок с другими потоками), papaya предоставляет операции по атомарной модификации отдельных записей, использующие переданные коллбеки для выполнения нужной операции. Для наиболее ходовых операций есть отдельные методы, а для тех, которые в эти методы не укладываются, есть операция compute. Коллбек, переданный в этот метод, должен возвращать значение типа Operation, описывающий требуемое действие:
В конце автор сравнивает свою реализацию с другими подобными библиотеками для Rust и поясняет, почему может иметь смысл использовать их вместо papaya.
Designing A Fast Concurrent Hash Table
Статья о дизайне papaya, многопоточной в основном lock-free хэш-мапы с упором на пропускную способность на операциях чтения из мапы и предсказуемые задержки (без пиков). Также пока что является, кажется, единственной подобной структурой данных, которую можно использовать из асинхронного кода.
Для того, чтобы избежать пиков задержки, использует инкрементальное изменение размера — и это одно из немногих мест, где используются блокировки.
Так как многопоточная мапа по определению не может иметь аналог entry API (по крайней мере, без кучи тонкостей из-за потенциальных гонок с другими потоками), papaya предоставляет операции по атомарной модификации отдельных записей, использующие переданные коллбеки для выполнения нужной операции. Для наиболее ходовых операций есть отдельные методы, а для тех, которые в эти методы не укладываются, есть операция compute. Коллбек, переданный в этот метод, должен возвращать значение типа Operation, описывающий требуемое действие:
enum Operation<V, T> {
Insert(V),
Remove,
Abort(T),
}
В конце автор сравнивает свою реализацию с другими подобными библиотеками для Rust и поясняет, почему может иметь смысл использовать их вместо papaya.
Ibraheem Ahmed
Designing A Fast Concurrent Hash Table
I recently released papaya, a fast and feature-complete concurrent hash table for Rust. In this post I want to dive into the design and research that went into creating it, as well as why you might consider using it over existing solutions.
🔥7❤5
#prog #rust #rustlib
walkdir — кросс-платформерная библиотека для рекурсивного обхода директорий от Andrew Gallant aka Burntsushi.
Библиотека умеет обнаруживает циклы символьных ссылок и сообщать в этих случаях об ошибке.
Небольшое неудобство заключается в том, что
walkdir — кросс-платформерная библиотека для рекурсивного обхода директорий от Andrew Gallant aka Burntsushi.
use walkdir::WalkDir;
for entry in WalkDir::new("foo").min_depth(1).max_depth(3) {
println!("{}", entry?.path().display());
}
Библиотека умеет обнаруживает циклы символьных ссылок и сообщать в этих случаях об ошибке.
Небольшое неудобство заключается в том, что
.filter()
на итераторе не будет предотвращать заход в пропущенные директории, для этого нужно на итераторе вызвать .filter_entry()
. Пример из документации для пропуска скрытых файлов на *nix-системах:use walkdir::{DirEntry, WalkDir};
fn is_hidden(entry: &DirEntry) -> bool {
entry.file_name()
.to_str()
.map(|s| s.starts_with("."))
.unwrap_or(false)
}
for entry in WalkDir::new("foo")
.into_iter()
.filter_entry(|e| !is_hidden(e)) {
println!("{}", entry?.path().display());
}
docs.rs
walkdir - Rust
Crate `walkdir` provides an efficient and cross platform implementation of recursive directory traversal. Several options are exposed to control iteration, such as whether to follow symbolic links (default off), limit the maximum number of simultaneous open…
👍9❤🔥4
#prog #rustlib
include-utils — библиотека для включения в исходники только части текста из указанного файла. Макрос include_md! также позволяет ссылаться на нужные части файла не через номера строк, а через указание секций, как это сделано в mdbook.
include-utils — библиотека для включения в исходники только части текста из указанного файла. Макрос include_md! также позволяет ссылаться на нужные части файла не через номера строк, а через указание секций, как это сделано в mdbook.
👍3🤯3❤1
#prog #rust #rustlib
embed_it — макрос, который позволяет включить в бинарь целую директорию ресурсов и потом обращаться к вложенным директориям и файлам по именам, причём как по статическим (в виде геттеров с теми же именами, что и файлы), так и по рантаймовым. Посмотрите пример в README.
embed_it — макрос, который позволяет включить в бинарь целую директорию ресурсов и потом обращаться к вложенным директориям и файлам по именам, причём как по статическим (в виде геттеров с теми же именами, что и файлы), так и по рантаймовым. Посмотрите пример в README.
GitHub
GitHub - riberk/embed_it: Include your assets statically into your application with a strict structure
Include your assets statically into your application with a strict structure - riberk/embed_it
👍6
#prog #rustlib #article
parser combinators with nom 8 are here!
(восьмая мажорная версия — это прям дофига для Rust-библиотек)
Geoffroy Couprie рассказывает о новой архитектуре nom. В этой версии он позаимствовал из chumsky подход к архитектуре парсеров. Про этот подход ещё в 2022 году писал Niko Matsakis в статье Many modes: a GAT pattern, которая демонстрировала, как GAT могут пригодиться в реальных библиотеках, и таким образом обосновывала необходимость иметь GAT в языке.
В nom 8 парсером является то, что реализует трейт Parser. Вот как выглядит его определение за вычетом методов с реализацией по умолчанию:
Параметр
Трейт Mode является ключом к новым возможностям. Реализации этого трейта позволяют абстрагироваться над "выходом парсера, имеющего отношение к T":
Для чего всё это нужно? Дело в том, что в nom есть комбинаторы, которые используют переданный аргументом парсер, но при этом не используют то, что этот парсер выдаёт в качестве результата. В качестве примера таких комбинаторов можно назвать preceded и delimited. Если конструирование значения является дорогим (скажем, это условный separated_list0, который собирает результаты разбора под-парсеров в вектор), то запускать парсер только ради того, чтобы отбросить его значение, будет довольно расточительно.
В самом nom определены два типа, которые реализовывают
Так как ошибка парсера тоже может дорого конструироваться, тип
Как вы могли заметить, у
Новый подход позволяет написать ветвление по
parser combinators with nom 8 are here!
(восьмая мажорная версия — это прям дофига для Rust-библиотек)
Geoffroy Couprie рассказывает о новой архитектуре nom. В этой версии он позаимствовал из chumsky подход к архитектуре парсеров. Про этот подход ещё в 2022 году писал Niko Matsakis в статье Many modes: a GAT pattern, которая демонстрировала, как GAT могут пригодиться в реальных библиотеках, и таким образом обосновывала необходимость иметь GAT в языке.
В nom 8 парсером является то, что реализует трейт Parser. Вот как выглядит его определение за вычетом методов с реализацией по умолчанию:
trait Parser<Input> {
type Output;
type Error: ParseError<Input>;
fn process<OM: OutputMode>(
&mut self,
input: Input,
) -> PResult<OM, Input, Self::Output, Self::Error>;
}
Параметр
OM
реализует трейт OutputMode, реализации которого являются фактически type-level конфигом парсера:trait OutputMode {
type Output: Mode;
type Error: Mode;
type Incomplete: IsStreaming;
}
Трейт Mode является ключом к новым возможностям. Реализации этого трейта позволяют абстрагироваться над "выходом парсера, имеющего отношение к T":
trait Mode {
type Output<T>;
// методы для комбинирования и преобразовывания Output
}
Для чего всё это нужно? Дело в том, что в nom есть комбинаторы, которые используют переданный аргументом парсер, но при этом не используют то, что этот парсер выдаёт в качестве результата. В качестве примера таких комбинаторов можно назвать preceded и delimited. Если конструирование значения является дорогим (скажем, это условный separated_list0, который собирает результаты разбора под-парсеров в вектор), то запускать парсер только ради того, чтобы отбросить его значение, будет довольно расточительно.
В самом nom определены два типа, которые реализовывают
Mode
: Emit и Check. Emit
реализовывает Mode
с type Output<T> = T
, то есть парсер работает, как обычно. Check
же реализовывает Mode
с type Output<T> = ()
, то есть парсер работает, но отбрасывает результаты. Именно такое поведение годится для комбинаторов, которым не нужен результат под-парсера. Так как конечный парсер имеет методы, обобщённые по параметру OM
, реализующему OutputMode
, парсер не может сконструировать результат напрямую, а вынужден использовать для этого методы Mode
, определённые на OM::Output
. В случае Emit
эти методы просто применяют переданные функции к аргументам, а для Check
эти методы просто дропают переданные функции и возвращают ()
.Так как ошибка парсера тоже может дорого конструироваться, тип
OutputMode::Error
по аналогичным причинам также реализует Mode
. Это нужно, например, для opt, который делает парсер опциональным и по понятным причинам отбрасывает и разобранный результат, и ошибку.Как вы могли заметить, у
OutputMode
также есть параметр Incomplete
, реализующий трейт IsStreaming. Он отвечает за то, является ли недостаточный вход фатальной ошибкой или же одним из вариантов ошибки, от которой можно восстановиться. Раньше почти каждый базовый комбинатор nom существовал в двух версиях: streaming и complete. Это было нежелательно по нескольким причинам, главная из которых — разные сорта парсеров очень легко перепутать при написании своих парсеров и потом долго ловить непонятные ошибки. Ещё одним нежелательным следствием этого подхода стало, очевидно, дублирование кода. Разные версии этих парсеров по разному обрабатывали неполный вход, но за вычетом этого аспекта логика там была одинаковая.Новый подход позволяет написать ветвление по
OM::IsIstreaming::is_streaming()
и обработать оба варианта в одной функции, естественным образом собирая разные варианты реагирования на ошибку неполного входа в одном месте. Так как в nom оба типа, реализующих IsStreaming
— Streaming и Complete — в соответствующих методах просто возвращают true
и false
соответственно, компилятор может увидеть ветвление по константному значению и просто убрать одну из веток, избежав генерации ненужного кода.🔥7🎉2👌1
#prog #rust #rustlib
eval-macro — макрос, позволяющий генерировать код с использованием обычного кода на Rust. Посмотрите пример по ссылке.
Реализовано довольно проклято:
The content inside
eval-macro — макрос, позволяющий генерировать код с использованием обычного кода на Rust. Посмотрите пример по ссылке.
Реализовано довольно проклято:
The content inside
eval!
is pasted into the main function of a temporary Rust project created in $HOME/.cargo/eval-macro/<project-id>
. This project is created, compiled, executed, and removed at build time, and its stdout becomes the generated Rust code🌚15🥴11🤯1
#prog #rust #rustlib
seq — a
Написано, конечно же, Толяном.
seq — a
seq!
macro to repeat a fragment of source code and substitute into each repetition a sequential numeric counter.use seq_macro::seq;
fn main() {
let tuple = (1000, 100, 10);
let mut sum = 0;
// Expands to:
//
// sum += tuple.0;
// sum += tuple.1;
// sum += tuple.2;
seq!(N in 0..=2 {
sum += tuple.N;
});
assert_eq!(sum, 1110);
}
Написано, конечно же, Толяном.
❤8🤡1😐1
#prog #rust #rustasync #rustlib
async-std официально deprecated. Взамен советуют использовать smol и смежные крейты.
ДАВНО ПОРА
async-std официально deprecated. Взамен советуют использовать smol и смежные крейты.
ДАВНО ПОРА
👍7😭5🔥2🥰1😁1
#prog #rust #rustlib #article
Introducing facet: Reflection for Rust
Как сказано в facet.rs:
Сердце библиотеки — трейт Facet и derive-макрос для него. В отличие от других крейтов, которые ползают по определениям типов, facet генерирует не код обхода значений, а константы, которые описывают формы значений и потому могут быть утилизированы разными библиотеками разными способами. Из примеров: (де)сериализация, отладочная печать, ассерты с диффами (которые не полагаются на пост-обработку Debug-выхлопа). В силу того, что код не генерируется, эти реализации могут использовать нерекурсивные алгоритмы и таким образом избежать переполнение стека и легко регулировать глубину вложенности.
В статье рассказывается, зачем это создано и какие ещё преимущества даёт.
Introducing facet: Reflection for Rust
Как сказано в facet.rs:
the last proc macro / the last derive you’ll ever need
Сердце библиотеки — трейт Facet и derive-макрос для него. В отличие от других крейтов, которые ползают по определениям типов, facet генерирует не код обхода значений, а константы, которые описывают формы значений и потому могут быть утилизированы разными библиотеками разными способами. Из примеров: (де)сериализация, отладочная печать, ассерты с диффами (которые не полагаются на пост-обработку Debug-выхлопа). В силу того, что код не генерируется, эти реализации могут использовать нерекурсивные алгоритмы и таким образом избежать переполнение стека и легко регулировать глубину вложенности.
В статье рассказывается, зачем это создано и какие ещё преимущества даёт.
fasterthanli.me
Introducing facet: Reflection for Rust
I have long been at war against Rust compile times.
Part of the solution for me was to buy my way into Apple Silicon dreamland, where builds are, like… faster. I remember every time I SSH into an x...
Part of the solution for me was to buy my way into Apple Silicon dreamland, where builds are, like… faster. I remember every time I SSH into an x...
👍12❤5🔥2🤡1