diff --git a/.github/workflows/render.yml b/.github/workflows/render.yml new file mode 100644 index 0000000..e69d23a --- /dev/null +++ b/.github/workflows/render.yml @@ -0,0 +1,27 @@ +name: Render + +on: + push: + +jobs: + build: + runs-on: ubuntu-latest + + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + + steps: + - uses: actions/checkout@v3 + + - name: Render list + run: make render + + - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + with: + commit_message: Commit list + commit_user_name: Idiomatic Rust Bot + commit_user_email: bot@idiomatic.rs + commit_author: Idiomatic Rust Bot diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..afa6690 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +.PHONY: render +render: + cargo run --manifest-path=render/Cargo.toml \ No newline at end of file diff --git a/README.md b/README.md index 7686be9..1e7f273 100644 --- a/README.md +++ b/README.md @@ -1,133 +1,142 @@ + + ![Logo](assets/cover.jpg) [![Check Links](https://github.com/mre/idiomatic-rust/workflows/Check%20Links/badge.svg)](https://github.com/mre/idiomatic-rust/actions/workflows/check_links.yml) This repository collects resources for writing clean, idiomatic Rust code. [Please bring your own.](https://github.com/mre/idiomatic-rust/blob/master/CONTRIBUTING.md) :blush: -> *Idiomatic* coding means following the conventions of a given language. It is the most concise, convenient, and common way of accomplishing a task in that language, rather than forcing it to work in a way the author is familiar with from a different language. - Adapted from [Tim Mansfield](https://github.com/tim-hr/stuff/wiki/Idiomatic-coding) +> *Idiomatic* coding means following the conventions of a given language. It is +> the most concise, convenient, and common way of accomplishing a task in that +> language, rather than forcing it to work in a way the author is familiar with +> from a different language. - Adapted from [Tim +> Mansfield](https://github.com/tim-hr/stuff/wiki/Idiomatic-coding) ## ⚙ Projects -* [Rust Anthology](https://github.com/brson/rust-anthology) - The best short-form writing about Rust, collected. * [blessed.rs](https://blessed.rs) - An unofficial guide to the Rust ecosystem. Suggestions for popular, well-maintained crates. -* [cheats.rs - Idiomatic Rust tips](https://cheats.rs/#idiomatic-rust) - A list of quick tips to make your code more idiomatic. +* [cheats.rs - Idiomatic Rust tips](https://cheats.rs) - A list of quick tips to make your code more idiomatic. * [clippy](https://github.com/rust-lang/rust-clippy) - A bunch of lints to catch common mistakes and improve your Rust code. -* [Patterns](https://rust-unofficial.github.io/patterns/) - A catalogue of design patterns in Rust. * [Elements of Rust](https://github.com/ferrous-systems/elements-of-rust) - A collection of software engineering techniques for effectively expressing intent with Rust. +* [Patterns](https://rust-unofficial.github.io/patterns/) - A catalogue of design patterns in Rust. * [Possible Rust](https://www.possiblerust.com/) - A blog for intermediate Rust programmers exploring real-world code and design patterns. +* [Rust Anthology](https://github.com/brson/rust-anthology) - The best short-form writing about Rust, collected. * [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) - An extensive list of recommendations for idiomatic Rust APIs. * [Rust by Example](https://doc.rust-lang.org/rust-by-example/) - A community driven collection of example code which follow Rust best practices. ## 🏋 Workshops -* [Comprehensive Rust](https://github.com/google/comprehensive-rust) - A four day Rust course developed by the Android team, which covers all aspects of Rust, from basic syntax to generics and error handling. It also includes Android-specific content and touches on Rust ergonomics. -* [Build your own JIRA with Rust](https://github.com/LukeMathWalker/build-your-own-jira-with-rust/) - A test-driven workshop to learn Rust building your own JIRA clone! -* [Ferrous Systems Teaching Material](https://ferrous-systems.github.io/teaching-material/index.html) - Free workshop material produced by Ferrous Systems for trainings. The time for the full course is around three to four days. -* [PingCAP talent plan](https://github.com/pingcap/talent-plan) - A series of training courses about writing distributed systems in Rust. The courses primarily consist of projects where coding problems are presented, along with a partial implementation or API description, and a test suite. -* [Procedural Macros Workshop](https://github.com/dtolnay/proc-macro-workshop) - This repo contains a selection of projects designed to learn to write Rust procedural macros — Rust code that generates Rust code. -* [rust-lang/rustlings](https://github.com/rust-lang/rustlings) - 🦀 Small exercises to get you used to reading and writing Rust code! -* [Rust Development at Sentry](https://develop.sentry.dev/rust/) - A document that contains useful resources for getting started with Rust and adhering to the Sentry coding principles. -* [Rust 101](https://101-rs.tweede.golf/) - A Rust University course by tweede golf. +* [Build your own JIRA with Rust](https://github.com/LukeMathWalker/build-your-own-jira-with-rust/) - A test-driven workshop to learn Rust by building your own JIRA clone! +* [Comprehensive Rust](https://github.com/google/comprehensive-rust) - A four day Rust course developed by the Android team, covering all aspects of Rust. +* [Ferrous Systems Teaching Material](https://ferrous-systems.github.io/teaching-material/index.html) - Free workshop material produced by Ferrous Systems for trainings. +* [PingCAP talent plan](https://github.com/pingcap/talent-plan) - A series of training courses about writing distributed systems in Rust. +* [Procedural Macros Workshop](https://github.com/dtolnay/proc-macro-workshop) - A selection of projects designed to learn to write Rust procedural macros. +* [Rust 101](https://101-rs.tweede.golf/) - A Rust University course by tweede golf. +* [Rust Development at Sentry](https://develop.sentry.dev/rust/) - A document containing useful resources for getting started with Rust and adhering to Sentry coding principles. +* [rust-lang/rustlings](https://github.com/rust-lang/rustlings) - Small exercises to get you used to reading and writing Rust code. ## 📖 Books -* [Command Line Applications in Rust](https://rust-cli.github.io/book) - A tutorial on how to write CLI apps in Rust, learning many aspects of the ecosystem along the way. -* [Command-Line Rust](https://github.com/kyclark/command-line-rust) by [Ken Youens-Clark](https://github.com/kyclark) - Learn the language by writing Rust versions of common Unix coreutils like head, tail, cal, cut, comm, etc. -* [Discover the world of microcontrollers through Rust!](https://rust-embedded.github.io/discovery/) - This book is an introductory course on microcontroller-based embedded systems that uses Rust as the teaching language rather than the usual C/C++. -* [High Assurance Rust](https://highassurance.rs/) by [Tiemoko Ballo -](https://github.com/tnballo) - Developing Secure and Robust Software. Tackles implementing embedded-friendly data structures in an idiomatic way. -* [Rust Cookbook](https://github.com/rust-lang-nursery/rust-cookbook) - Examples that demonstrate good practices to accomplish common programming tasks in Rust. -* [Rust for Rustaceans](https://nostarch.com/rust-rustaceans) by [Jon Gjengset](https://github.com/jonhoo) - Covers how to design reliable, idiomatic, and ergonomic Rust programs based on best principles. +* [Command Line Applications in Rust](https://rust-cli.github.io/book) - A tutorial on how to write CLI apps in Rust, learning many aspects of the ecosystem. +* [Command-Line Rust](https://github.com/kyclark/command-line-rust) - Learn the language by writing Rust versions of common Unix coreutils. +* [Discover the world of microcontrollers through Rust!](https://rust-embedded.github.io/discovery/) - An introductory course on microcontroller-based embedded systems using Rust. +* [High Assurance Rust](https://highassurance.rs/) - Developing secure and robust software, focusing on embedded-friendly data structures in Rust. * [Programming Rust: Fast, Safe Systems Development](https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/) - A comprehensive Rust Programming Guide that covers most of Rust's features in detail. -* [Rust Atomics and Locks](https://marabos.nl/atomics/) by [Mara Bos](https://github.com/m-ou-se) - Helps Rust programmers of all levels gain a clear understanding of low-level concurrency. +* [Rust Atomics and Locks](https://marabos.nl/atomics/) - Helps Rust programmers of all levels gain a clear understanding of low-level concurrency. +* [Rust Cookbook](https://github.com/rust-lang-nursery/rust-cookbook) - Examples that demonstrate good practices to accomplish common programming tasks in Rust. +* [Rust for Rustaceans](https://nostarch.com/rust-rustaceans) - Covers how to design reliable, idiomatic, and ergonomic Rust programs based on best principles. ## 📰 Articles ### 2023 -* [Compile-Time Invariants in Rust](https://corrode.dev/blog/compile-time-invariants/) by [corrode Rust consulting](https://corrode.dev) - Shows how macros can be used to enforce invariants at compile-time. -* [Aim For Immutability in Rust](https://corrode.dev/blog/immutability/) by [corrode Rust consulting](https://corrode.dev) - Explains why variables are immutable in Rust by default. +* [Aim For Immutability in Rust](https://corrode.dev/blog/immutability/) - Explains why variables are immutable in Rust by default. +* [Compile-Time Invariants in Rust](https://corrode.dev/blog/compile-time-invariants/) - Shows how macros can be used to enforce invariants at compile-time. ### 2021 -* [Naming Your Lifetimes](https://www.possiblerust.com/pattern/naming-your-lifetimes) by [Possible Rust](https://www.possiblerust.com) - Explains how using longer, declarative lifetime names can help to disambiguate which borrow is which, and where it’s coming from. -* [Aiming for idiomatic Rust](https://web.archive.org/web/20221205112620/https://shane-o.dev/blog/aiming-for-idiomatic-rust) by [Shane Osbourne](https://shane-o.dev/) - Discusses different ways to solve a popular coding puzzle, "balanced brackets", in Rust. -* [Wrapping errors in Rust](https://edgarluque.com/blog/wrapping-errors-in-rust) by [Edgar Luque](https://github.com/edg-l) - Wrapping `reqwest::Error` and a custom error type as an enum to make library usage easier. Also mentions [thiserror](https://github.com/dtolnay/thiserror) to automate that process. -* [Hexagonal architecture in Rust](https://alexis-lozano.com/hexagonal-architecture-in-rust-1/) by [Alexis Lozano](https://github.com/alexislozano) - Describes how to build a Rust service using domain driven design and a test-first approach. +* [Hexagonal architecture in Rust](https://alexis-lozano.com/hexagonal-architecture-in-rust-1/) - Describes how to build a Rust service using domain driven design and a test-first approach. +* [Wrapping errors in Rust](https://edgarluque.com/blog/wrapping-errors-in-rust) - Wrapping 'reqwest::Error' and a custom error type as an enum to make library usage easier. +* [Aiming for idiomatic Rust](https://web.archive.org/web/20221203043933/https://shane-o.dev/blog/aiming-for-idiomatic-rust) - Discusses different ways to solve a popular coding puzzle, 'balanced brackets', in Rust. +* [Naming Your Lifetimes](https://www.possiblerust.com/pattern/naming-your-lifetimes) - Explains how using longer, declarative lifetime names can help to disambiguate which borrow is which. ### 2020 -* [Context-preserving error handling](https://kazlauskas.me/entries/errors) by [Simonas Kazlauskas](https://github.com/nagisa) - Explains how to use crates like `thiserror` in combination with `map_err` to add context to errors to prevent information loss. -* [Refactoring Rust Transpiled from C](https://immunant.com/blog/2020/09/transpiled_c_safety/) by [Per Larsen](https://github.com/thedataking) - Describes how to lift a C-project that was automatically converted to unsafe Rust with C2Rust to safer, more idiomatic Rust with some human intervention. -* [Learning Rust through open source and live code reviews](https://loige.co/learning-rust-through-open-source-and-live-code-reviews/) by [Luciano Mammino](https://github.com/lmammino) and [Stefano Abalsamo](https://github.com/stefanoabalsamo79) - Covers patterns like [FromStr](https://doc.rust-lang.org/std/str/trait.FromStr.html) and exposing a CLI and a library in one crate. -* [Guide on how to write documentation for a Rust crate](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate) - Writing good documentation with rustdoc including many examples. * [Are out parameters idiomatic in Rust?](https://steveklabnik.com/writing/are-out-paramters-idiomatic-in-rust) - Discusses the pros and cons of functions returning a value vs. modifying a parameter in-place. +* [Guide on how to write documentation for a Rust crate](https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate) - Writing good documentation with rustdoc including many examples. +* [Learning Rust through open source and live code reviews](https://loige.co/learning-rust-through-open-source-and-live-code-reviews/) - Covers patterns like 'FromStr' and exposing a CLI and a library in one crate. +* [Refactoring Rust Transpiled from C](https://immunant.com/blog/2020/09/transpiled_c_safety/) - Describes how to lift a C-project that was automatically converted to unsafe Rust to safer, more idiomatic Rust. +* [Context-preserving error handling](https://kazlauskas.me/entries/errors) - Explains how to use crates like 'thiserror' in combination with 'map_err' to add context to errors. ### 2019 -* [Await a minute](https://docs.rs/dtolnay/0.0.3/dtolnay/macro._01__await_a_minute.html) by [David Tolnay](https://github.com/dtolnay) - Example code for moving from raw futures to async/await syntax to improve error handling, native control flow, and borrowing. -* [Taking string arguments in Rust](http://xion.io/post/code/rust-string-args.html) by [@Xion](https://github.com/Xion) - Discussing how to avoid subtle issues with string handling and when to use `str` (the string slice) and `String` (the owned/allocated string). -* [Rust Patterns: Enums Instead Of Booleans](http://blakesmith.me/2019/05/07/rust-patterns-enums-instead-of-booleans.html) by [Blake Smith](https://github.com/blakesmith) - Discusses how using enums instead of booleans can be useful to express intent more clearly without sacrificing safety thanks to Rust's strong semantics (like exhaustive pattern matching). +* [Rust Patterns: Enums Instead Of Booleans](http://blakesmith.me/2019/05/07/rust-patterns-enums-instead-of-booleans.html) - Discusses how using enums instead of booleans can express intent more clearly in Rust. +* [Taking string arguments in Rust](http://xion.io/post/code/rust-string-args.html) - Discussing how to avoid subtle issues with string handling and when to use 'str' vs 'String'. +* [Await a minute](https://docs.rs/dtolnay/0.0.3/dtolnay/macro._01__await_a_minute.html) - Example code for moving from raw futures to async/await syntax to improve error handling. ### 2018 -* [Programming an ARM microcontroller in Rust at four different levels of abstraction](https://pramode.in/2018/02/20/programming-a-microcontroller-in-rust-at-four-levels-of-abstraction/) by [Pramode C.E ](https://pramode.in/) - Demonstrates how Rust helps to move from brittle, low-level embedded code to high-level abstractions with zero cost. +* [Programming an ARM microcontroller in Rust at four different levels of abstraction](https://pramode.in/2018/02/20/programming-a-microcontroller-in-rust-at-four-levels-of-abstraction/) - Demonstrates how Rust helps to move from low-level embedded code to high-level abstractions. ### 2017 -* [Iteration patterns for Result & Option](http://xion.io/post/code/rust-iter-patterns.html) by [@Xion](https://github.com/Xion) - Explores how to filter and partition iterators of Result and Option types idiomatically. -* [Lessons learned redesigning and refactoring a Rust Library](https://web.archive.org/web/20220126172949/https://blog.mgattozzi.dev/refactor-rust/) by [@mgattozzi](https://github.com/mgattozzi) - `RefCell`, the builder pattern and more. -* [Math with distances in Rust: safety and correctness across units](https://ferrisellis.com/content/rust-implementing-units-for-types/) by [@code-ape](https://github.com/code-ape) - How to create a system to cleanly and safely do arithmetic with lengths. -* [The balance between cost, useability and soundness in C bindings, and Rust-SDL2's release](https://web.archive.org/web/20190509123207/https://cobrand.github.io/rust/sdl2/2017/05/07/the-balance-between-soundness-cost-useability.html) by [@Cobrand](https://github.com/Cobrand) - Writing safe, sound, idiomatic libraries despite the limitations of the borrow checker. +* [The balance between cost, useability and soundness in C bindings, and Rust-SDL2's release](https://web.archive.org/web/20190509123207/https://cobrand.github.io/rust/sdl2/2017/05/07/the-balance-between-soundness-cost-useability.html) - Writing safe, sound, idiomatic libraries despite the limitations of the borrow checker. +* [Math with distances in Rust: safety and correctness across units](https://ferrisellis.com/content/rust-implementing-units-for-types/) - How to create a system to cleanly and safely do arithmetic with lengths. +* [Lessons learned redesigning and refactoring a Rust Library](https://web.archive.org/web/20220126172949/https://blog.mgattozzi.dev/refactor-rust/) - 'RefCell', the builder pattern and more. +* [Iteration patterns for Result & Option](http://xion.io/post/code/rust-iter-patterns.html) - Explores how to filter and partition iterators of Result and Option types idiomatically. ### 2016 -* [Russian Dolls and clean Rust code](https://web.archive.org/web/20220126183049/https://blog.mgattozzi.dev/russian-dolls/) by [@mgattozzi](https://github.com/mgattozzi) - How to use the full power of `Option` and `Result` (especially `and_then()` and `unwrap_or()`). -* [Elegant Library APIs in Rust](https://deterministic.space/elegant-apis-in-rust.html) by [@killercup](https://github.com/killercup) - Many helpful tips and tricks for writing libraries in Rust. -* [Teaching libraries through good documentation](https://deterministic.space/teaching-libraries.html) by [@killercup](https://github.com/killercup) - How to use the full power of Rust's documentation support (e.g. doc tests) -* [Pretty State Machine Patterns in Rust](https://hoverbear.org/2016/10/12/rust-state-machine-pattern/) by [@hoverbear](https://github.com/Hoverbear) - How to represent a State Machine in an expressive and understandable way in Rust. -* [Ripgrep Code Review](https://blog.mbrt.dev/posts/ripgrep/) by [@mbrt](https://github.com/mbrt) - An analysis of the popular `ripgrep` tool's source code. -* [Rustic Bits](https://llogiq.github.io/2016/02/11/rustic.html) by [@llogiq](https://github.com/llogiq/) - Small things that make for rustic code. -* [Convenient and idiomatic conversions in Rust](https://ricardomartins.cc/2016/08/03/convenient_and_idiomatic_conversions_in_rust) by [meqif](https://github.com/meqif) - Explains `From`, `Into`, `TryFrom`, `TryInto`, `AsRef` and `AsMut` with pratical examples. -* [Idiomatic tree and graph like structures in Rust](https://rust-leipzig.github.io/architecture/2016/12/20/idiomatic-trees-in-rust/) by [saschagrunert](https://github.com/saschagrunert) - Introduction to safe, dynamic, arena based tree structures without using lifetimes. +* [Idiomatic tree and graph like structures in Rust](https://rust-leipzig.github.io/architecture/2016/12/20/idiomatic-trees-in-rust/) - Introduction to safe, dynamic, arena based tree structures without using lifetimes. +* [Convenient and idiomatic conversions in Rust](https://ricardomartins.cc/2016/08/03/convenient_and_idiomatic_conversions_in_rust) - Explains 'From', 'Into', 'TryFrom', 'TryInto', 'AsRef' and 'AsMut' with practical examples. +* [Rustic Bits](https://llogiq.github.io/2016/02/11/rustic.html) - Small things that make for rustic code. +* [Ripgrep Code Review](https://blog.mbrt.dev/posts/ripgrep/) - An analysis of the popular 'ripgrep' tool's source code. +* [Pretty State Machine Patterns in Rust](https://hoverbear.org/2016/10/12/rust-state-machine-pattern/) - How to represent a State Machine in an expressive and understandable way in Rust. +* [Teaching libraries through good documentation](https://deterministic.space/teaching-libraries.html) - How to use the full power of Rust's documentation support (e.g. doc tests). +* [Elegant Library APIs in Rust](https://deterministic.space/elegant-apis-in-rust.html) - Many helpful tips and tricks for writing libraries in Rust. +* [Russian Dolls and clean Rust code](https://web.archive.org/web/20220126183049/https://blog.mgattozzi.dev/russian-dolls/) - How to use the full power of 'Option' and 'Result' (especially 'and_then()' and 'unwrap_or()'). ### 2015 -* [Rust traits for developer friendly libraries](https://benashford.github.io/blog/2015/05/24/rust-traits-for-developer-friendly-libraries/) by [@benashford](https://github.com/benashford) - Thoughts about implementing good Rust libraries. -* [Error Handling in Rust](https://blog.burntsushi.net/rust-error-handling/) by [@BurntSushi](https://github.com/BurntSushi) - Understanding and handling errors in Rust in an idiomatic way. -* [Creating a Rust function that accepts String or &str](https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html) by [@hjr](https://github.com/hjr3) - How to make calling your code both ergonomic and fast (zero-allocation). -* [Creating a Rust function that returns a &str or String](https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html) by [@hjr](https://github.com/hjr3) - How `Into` and `Cow` (Clone-on-write) work together to avoid allocations for string types. -* [Effectively Using Iterators In Rust](https://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html) by [@hjr](https://github.com/hjr3) - Explanation of the `Iter` and `IntoIter` traits and how loops actually work in Rust. -* [Strategies for solving 'cannot move out of' borrowing errors in Rust](https://hermanradtke.com/2015/06/09/strategies-for-solving-cannot-move-out-of-borrowing-errors-in-rust.html) by [@hjr](https://github.com/hjr3) - Practical tips to help understand the borrow-checker and move semantics. -* [Rayon: data parallelism in Rust](https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/) by [@nikomatsakis](https://github.com/nikomatsakis) - Writing elegant parallel code in Rust. +* [Rayon: data parallelism in Rust](https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/) - Writing elegant parallel code in Rust. +* [Strategies for solving 'cannot move out of' borrowing errors in Rust](https://hermanradtke.com/2015/06/09/strategies-for-solving-cannot-move-out-of-borrowing-errors-in-rust.html) - Practical tips to help understand the borrow-checker and move semantics. +* [Effectively Using Iterators In Rust](https://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html) - Explanation of the 'Iter' and 'IntoIter' traits and how loops actually work in Rust. +* [Creating a Rust function that returns a &str or String](https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html) - How 'Into' and 'Cow' (Clone-on-write) work together to avoid allocations for string types. +* [Creating a Rust function that accepts String or &str](https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html) - How to make calling your code both ergonomic and fast (zero-allocation). +* [Error Handling in Rust](https://blog.burntsushi.net/rust-error-handling/) - Understanding and handling errors in Rust in an idiomatic way. +* [Rust traits for developer friendly libraries](https://benashford.github.io/blog/2015/05/24/rust-traits-for-developer-friendly-libraries/) - Thoughts about implementing good Rust libraries. + ## 🎤 Talks ### 2023 -* Tricks of the Trait: Enabling Ergonomic Extractors [[Video](https://www.youtube.com/watch?v=7DOYtnCXucw)] by [Rob Ede](https://github.com/robjtede) - Rust Nation UK, Feb. 2023 +* Tricks of the Trait: Enabling Ergonomic Extractors - Rust Nation UK, Feb. 2023 [[Video](https://www.youtube.com/watch?v=7DOYtnCXucw)] ### 2022 -* Nine Rules for Elegant Rust Library APIs [[Video](https://www.youtube.com/watch?v=6-8-9ZV-2WQ)] by [Carl Kadie](https://www.linkedin.com/in/carlk/) - Seattle Rust Meetup, Sep. 2022 -* Ergonomic APIs for hard problems [[Video](https://www.youtube.com/watch?v=Phk0C-kLlho)] [[Slides](https://docs.google.com/presentation/d/1P8Su5mZSYkfZ1A9mPAaKag-vtXmVD8nUBD7Ym-pfwJM)] by [Raph Levien](https://levien.com/) - RustLab Conference, October 2022 +* Ergonomic APIs for hard problems - RustLab Conference, October 2022 [[Video](https://www.youtube.com/watch?v=Phk0C-kLlho)] +* Nine Rules for Elegant Rust Library APIs - Seattle Rust Meetup, Sep. 2022 [[Video](https://www.youtube.com/watch?v=6-8-9ZV-2WQ)] ### 2020 -* Macros for a More Productive Rust [[Video](https://www.youtube.com/watch?v=dZiWkbnaQe8)] by [@jam1garner](https://github.com/jam1garner) - RustConf 2020 +* Macros for a More Productive Rust - RustConf 2020 [[Video](https://www.youtube.com/watch?v=dZiWkbnaQe8)] ### 2019 -* Making Rust Delightful [[Video](https://www.youtube.com/watch?v=YSEx8wtlPWc)] by [@nrc](https://github.com/nrc/) - RustCon Asia 2019 +* Making Rust Delightful - RustCon Asia 2019 [[Video](https://www.youtube.com/watch?v=YSEx8wtlPWc)] ### 2018 -* Idiomatic Rust - Writing Concise and Elegant Rust Code [[Video](https://www.youtube.com/watch?v=P2mooqNMxMs)] [[Slides](https://speakerdeck.com/mre/idiomatic-rust-writing-concise-and-elegant-rust-code)] by [@mre](https://github.com/mre) - FOSDEM 2018 +* Idiomatic Rust - Writing Concise and Elegant Rust Code - FOSDEM 2018 [[Video](https://www.youtube.com/watch?v=P2mooqNMxMs)] ### 2017 -* Idiomatic Rust Libraries [[Video](https://www.youtube.com/watch?v=0zOg8_B71gE)] [[Slides](https://killercup.github.io/rustfest-idiomatic-libs/index.html#/)] by [@killercup](https://github.com/killercup) - Rustfest Kiev -* What's so hard about writing a Slack Client in Rust? [[Video](https://www.youtube.com/watch?v=rrtJh1kz1Ms)] [[Slides](https://speakerdeck.com/mre/whats-so-hard-about-writing-a-slack-client-in-rust)] by [@mre](https://github.com/mre) - Rust Cologne Meetup +* Idiomatic Rust Libraries - Rustfest Kiev [[Video](https://www.youtube.com/watch?v=0zOg8_B71gE)] + ## 💬 Forum @@ -137,8 +146,9 @@ This repository collects resources for writing clean, idiomatic Rust code. [Plea ### 2017 -* [Which is more idiomatic? Functional, imperative or a mix?](https://users.rust-lang.org/t/which-is-more-idiomatic-functional-imperative-or-a-mix/11278) * [An idiomatic way to sum up values in a multidimensional Array](https://users.rust-lang.org/t/an-idiomatic-way-to-sum-up-values-in-a-multidimensional-array/9485) +* [Which is more idiomatic? Functional, imperative or a mix?](https://users.rust-lang.org/t/which-is-more-idiomatic-functional-imperative-or-a-mix/11278) + ## 📜 History diff --git a/render/.gitignore b/render/.gitignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/render/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/render/Cargo.lock b/render/Cargo.lock new file mode 100644 index 0000000..7c75992 --- /dev/null +++ b/render/Cargo.lock @@ -0,0 +1,271 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "askama" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" +dependencies = [ + "askama_derive", + "askama_escape", + "humansize", + "num-traits", + "percent-encoding", +] + +[[package]] +name = "askama_derive" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" +dependencies = [ + "askama_parser", + "basic-toml", + "mime", + "mime_guess", + "proc-macro2", + "quote", + "serde", + "syn", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "askama_parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" +dependencies = [ + "nom", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "basic-toml" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" +dependencies = [ + "serde", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + +[[package]] +name = "indexmap" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "render" +version = "0.1.0" +dependencies = [ + "askama", + "indexmap", + "itertools", + "serde", + "serde_json", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/render/Cargo.toml b/render/Cargo.toml new file mode 100644 index 0000000..da48b88 --- /dev/null +++ b/render/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "render" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +askama = "0.12.1" +indexmap = "2.2.1" +itertools = "0.12.1" +serde = { version = "1.0.196", features = ["serde_derive"] } +serde_json = "1.0.113" diff --git a/render/src/main.rs b/render/src/main.rs new file mode 100644 index 0000000..d47e3df --- /dev/null +++ b/render/src/main.rs @@ -0,0 +1,77 @@ +use std::fs; + +use askama::Template; +use indexmap::IndexMap; +use itertools::Itertools; +use serde::{Deserialize, Serialize}; + +#[derive(Template)] +#[template(path = "README.md")] +struct ReadmeTemplate { + projects: Vec, + workshops: Vec, + books: Vec, + articles: YearMap, + talks: YearMap, + forum: YearMap, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +struct Resource { + title: String, + url: String, + description: String, + tags: Vec, + official: bool, + year: usize, + #[serde(rename = "difficultyLevel")] + difficulty_level: String, + duration: Option, + #[serde(rename = "interactivityLevel")] + interactivity_level: String, + free: bool, + category: String, +} + +type Resources = Vec; + +type YearMap = IndexMap; + +fn group_by_year(resources: &Resources, category: &str) -> YearMap { + resources + .iter() + .filter(|r| r.category == category) + .sorted_by_key(|r| r.year) + .rev() + .fold(YearMap::new(), |mut map, r| { + map.entry(r.year).or_insert_with(Vec::new).push(r.clone()); + map + }) +} + +fn sort_by_title(resources: &Resources, category: &str) -> Resources { + resources + .iter() + .filter(|r| r.category == category) + .sorted_by_key(|r| r.title.to_lowercase()) + .cloned() + .collect() +} + +fn main() -> Result<(), Box> { + let file = std::fs::File::open("resources.json")?; + let resources: Resources = serde_json::from_reader(file)?; + + let readme = ReadmeTemplate { + projects: sort_by_title(&resources, "project"), + workshops: sort_by_title(&resources, "workshop"), + books: sort_by_title(&resources, "book"), + articles: group_by_year(&resources, "article"), + talks: group_by_year(&resources, "talk"), + forum: group_by_year(&resources, "forum"), + }; + + fs::write("README.md", readme.render()?)?; + + Ok(()) +} diff --git a/render/templates/README.md b/render/templates/README.md new file mode 100644 index 0000000..6d46692 --- /dev/null +++ b/render/templates/README.md @@ -0,0 +1,71 @@ + + +![Logo](assets/cover.jpg) + +[![Check Links](https://github.com/mre/idiomatic-rust/workflows/Check%20Links/badge.svg)](https://github.com/mre/idiomatic-rust/actions/workflows/check_links.yml) + +This repository collects resources for writing clean, idiomatic Rust code. [Please bring your own.](https://github.com/mre/idiomatic-rust/blob/master/CONTRIBUTING.md) :blush: + +> *Idiomatic* coding means following the conventions of a given language. It is +> the most concise, convenient, and common way of accomplishing a task in that +> language, rather than forcing it to work in a way the author is familiar with +> from a different language. - Adapted from [Tim +> Mansfield](https://github.com/tim-hr/stuff/wiki/Idiomatic-coding) + +## ⚙ Projects +{% for project in projects %} +* [{{ project.title }}]({{ project.url }}) - {{ project.description }} +{%- endfor %} + +## 🏋 Workshops +{% for workshop in workshops %} +* [{{ workshop.title }}]({{ workshop.url }}) - {{ workshop.description }} +{%- endfor %} + +## 📖 Books +{% for book in books %} +* [{{ book.title }}]({{ book.url }}) - {{ book.description }} +{%- endfor %} + +## 📰 Articles +{% for (year, resources) in articles %} +### {{ year }} + +{% for resource in resources -%} +* [{{ resource.title }}]({{ resource.url }}) - {{ resource.description }} +{% endfor %} +{%- endfor %} + +## 🎤 Talks +{% for (year, resources) in talks %} +### {{ year }} + +{% for resource in resources -%} +* {{ resource.title }} - {{ resource.description }} [[Video]({{ resource.url }})] +{% endfor %} +{%- endfor %} + +## 💬 Forum +{% for (year, resources) in forum %} +### {{ year }} + +{% for resource in resources -%} +* [{{ resource.title }}]({{ resource.url }}) +{% endfor %} +{%- endfor %} + +## 📜 History + +Coming from Python, I loved the guidelines on how *idiomatic Python* looks like. I was inspired by the likes of Peter Norvig, who wrote amazing articles on [spellcheckers](https://norvig.com/spell-correct.html) and [sudoku solvers](https://norvig.com/sudoku.html); and, of course, the [Zen of Python](https://www.python.org/dev/peps/pep-0020/). For Rust, there is no such thing as the Zen of Python, however, so I started collecting my own resources. +The goal of this project is to create a peer-reviewed collection of articles/talks/repos, which teach idiomatic Rust style. It's a community project and you can contribute. + +## 🔏 License + +[![CC0](https://i.creativecommons.org/p/zero/1.0/88x31.png)](https://creativecommons.org/publicdomain/zero/1.0/) + +To the extent possible under law, [Matthias Endler](https://endler.dev) has waived all copyright and related or neighboring rights to this work. +Logo adapted from [FreePik.com](https://www.freepik.com/free-vector/crabs-pattern-design_1093131.htm). + diff --git a/resources.json b/resources.json new file mode 100644 index 0000000..b71902b --- /dev/null +++ b/resources.json @@ -0,0 +1,1152 @@ +[ + { + "title": "Rust Anthology", + "url": "https://github.com/brson/rust-anthology", + "description": "The best short-form writing about Rust, collected.", + "tags": [ + "anthology", + "writing", + "collection" + ], + "official": false, + "year": 2018, + "difficultyLevel": "all", + "duration": null, + "interactivityLevel": "low", + "free": true, + "category": "project" + }, + { + "title": "blessed.rs", + "url": "https://blessed.rs", + "description": "An unofficial guide to the Rust ecosystem. Suggestions for popular, well-maintained crates.", + "tags": [ + "guide", + "ecosystem", + "crates" + ], + "official": false, + "year": 2019, + "difficultyLevel": "all", + "duration": null, + "interactivityLevel": "medium", + "free": true, + "category": "project" + }, + { + "title": "cheats.rs - Idiomatic Rust tips", + "url": "https://cheats.rs", + "description": "A list of quick tips to make your code more idiomatic.", + "tags": [ + "tips", + "idiomatic", + "quick" + ], + "official": false, + "year": 2020, + "difficultyLevel": "all", + "duration": null, + "interactivityLevel": "low", + "free": true, + "category": "project" + }, + { + "title": "clippy", + "url": "https://github.com/rust-lang/rust-clippy", + "description": "A bunch of lints to catch common mistakes and improve your Rust code.", + "tags": [ + "lints", + "code-quality", + "tool" + ], + "official": true, + "year": 2015, + "difficultyLevel": "all", + "duration": null, + "interactivityLevel": "low", + "free": true, + "category": "project" + }, + { + "title": "Patterns", + "url": "https://rust-unofficial.github.io/patterns/", + "description": "A catalogue of design patterns in Rust.", + "tags": [ + "design-patterns", + "catalogue", + "best-practices" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": null, + "interactivityLevel": "low", + "free": true, + "category": "project" + }, + { + "title": "Elements of Rust", + "url": "https://github.com/ferrous-systems/elements-of-rust", + "description": "A collection of software engineering techniques for effectively expressing intent with Rust.", + "tags": [ + "software-engineering", + "techniques", + "best-practices" + ], + "official": false, + "year": 2019, + "difficultyLevel": "advanced", + "duration": null, + "interactivityLevel": "medium", + "free": true, + "category": "project" + }, + { + "title": "Possible Rust", + "url": "https://www.possiblerust.com/", + "description": "A blog for intermediate Rust programmers exploring real-world code and design patterns.", + "tags": [ + "blog", + "intermediate", + "design-patterns" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": null, + "interactivityLevel": "medium", + "free": true, + "category": "project" + }, + { + "title": "Rust API Guidelines", + "url": "https://rust-lang.github.io/api-guidelines/", + "description": "An extensive list of recommendations for idiomatic Rust APIs.", + "tags": [ + "api", + "guidelines", + "best-practices" + ], + "official": true, + "year": 2017, + "difficultyLevel": "intermediate", + "duration": null, + "interactivityLevel": "low", + "free": true, + "category": "project" + }, + { + "title": "Rust by Example", + "url": "https://doc.rust-lang.org/rust-by-example/", + "description": "A community driven collection of example code which follow Rust best practices.", + "tags": [ + "examples", + "community", + "best-practices" + ], + "official": false, + "year": 2015, + "difficultyLevel": "all", + "duration": null, + "interactivityLevel": "high", + "free": true, + "category": "project" + }, + { + "title": "Comprehensive Rust", + "url": "https://github.com/google/comprehensive-rust", + "description": "A four day Rust course developed by the Android team, covering all aspects of Rust.", + "tags": [ + "course", + "learning", + "comprehensive" + ], + "official": true, + "year": 2021, + "difficultyLevel": "all", + "duration": "4 days", + "interactivityLevel": "high", + "free": true, + "category": "workshop" + }, + { + "title": "Build your own JIRA with Rust", + "url": "https://github.com/LukeMathWalker/build-your-own-jira-with-rust/", + "description": "A test-driven workshop to learn Rust by building your own JIRA clone!", + "tags": [ + "test-driven", + "project" + ], + "official": true, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "workshop" + }, + { + "title": "Ferrous Systems Teaching Material", + "url": "https://ferrous-systems.github.io/teaching-material/index.html", + "description": "Free workshop material produced by Ferrous Systems for trainings.", + "tags": [ + "material", + "training" + ], + "official": true, + "year": 2019, + "difficultyLevel": "all", + "duration": "3-4 days", + "interactivityLevel": "medium", + "free": true, + "category": "workshop" + }, + { + "title": "PingCAP talent plan", + "url": "https://github.com/pingcap/talent-plan", + "description": "A series of training courses about writing distributed systems in Rust.", + "tags": [ + "training", + "distributed-systems", + "course" + ], + "official": true, + "year": 2018, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "workshop" + }, + { + "title": "Procedural Macros Workshop", + "url": "https://github.com/dtolnay/proc-macro-workshop", + "description": "A selection of projects designed to learn to write Rust procedural macros.", + "tags": [ + "macros", + "coding" + ], + "official": true, + "year": 2019, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "workshop" + }, + { + "title": "rust-lang/rustlings", + "url": "https://github.com/rust-lang/rustlings", + "description": "Small exercises to get you used to reading and writing Rust code.", + "tags": [ + "exercises", + "learning", + "beginner" + ], + "official": true, + "year": 2018, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "workshop" + }, + { + "title": "Rust Development at Sentry", + "url": "https://develop.sentry.dev/rust/", + "description": "A document containing useful resources for getting started with Rust and adhering to Sentry coding principles.", + "tags": [ + "guide", + "coding-principles", + "development" + ], + "official": true, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "workshop" + }, + { + "title": "Rust 101", + "url": "https://101-rs.tweede.golf/", + "description": "A Rust University course by tweede golf.", + "tags": [ + "course", + "university", + "learning" + ], + "official": false, + "year": 2019, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "workshop" + }, + { + "title": "Command Line Applications in Rust", + "url": "https://rust-cli.github.io/book", + "description": "A tutorial on how to write CLI apps in Rust, learning many aspects of the ecosystem.", + "tags": [ + "tutorial", + "cli", + "ecosystem" + ], + "official": false, + "year": 2024, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "book" + }, + { + "title": "Command-Line Rust", + "url": "https://github.com/kyclark/command-line-rust", + "description": "Learn the language by writing Rust versions of common Unix coreutils.", + "tags": [ + "unix", + "coreutils", + "learning" + ], + "official": false, + "year": 2022, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "book" + }, + { + "title": "Discover the world of microcontrollers through Rust!", + "url": "https://rust-embedded.github.io/discovery/", + "description": "An introductory course on microcontroller-based embedded systems using Rust.", + "tags": [ + "embedded-systems", + "microcontroller", + "course" + ], + "official": false, + "year": 2023, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "book" + }, + { + "title": "High Assurance Rust", + "url": "https://highassurance.rs/", + "description": "Developing secure and robust software, focusing on embedded-friendly data structures in Rust.", + "tags": [ + "security", + "robustness", + "embedded" + ], + "official": false, + "year": 2022, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "book" + }, + { + "title": "Rust Cookbook", + "url": "https://github.com/rust-lang-nursery/rust-cookbook", + "description": "Examples that demonstrate good practices to accomplish common programming tasks in Rust.", + "tags": [ + "examples", + "good-practices", + "programming" + ], + "official": false, + "year": 2021, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "book" + }, + { + "title": "Rust for Rustaceans", + "url": "https://nostarch.com/rust-rustaceans", + "description": "Covers how to design reliable, idiomatic, and ergonomic Rust programs based on best principles.", + "tags": [ + "design", + "idiomatic", + "ergonomic" + ], + "official": false, + "year": 2021, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "low", + "free": false, + "category": "book" + }, + { + "title": "Programming Rust: Fast, Safe Systems Development", + "url": "https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/", + "description": "A comprehensive Rust Programming Guide that covers most of Rust's features in detail.", + "tags": [ + "comprehensive", + "features", + "guide" + ], + "official": false, + "year": 2021, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "low", + "free": false, + "category": "book" + }, + { + "title": "Rust Atomics and Locks", + "url": "https://marabos.nl/atomics/", + "description": "Helps Rust programmers of all levels gain a clear understanding of low-level concurrency.", + "tags": [ + "concurrency", + "low-level", + "understanding" + ], + "official": false, + "year": 2023, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "book" + }, + { + "title": "Compile-Time Invariants in Rust", + "url": "https://corrode.dev/blog/compile-time-invariants/", + "description": "Shows how macros can be used to enforce invariants at compile-time.", + "tags": [ + "macros", + "invariants", + "compile-time" + ], + "official": false, + "year": 2023, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Aim For Immutability in Rust", + "url": "https://corrode.dev/blog/immutability/", + "description": "Explains why variables are immutable in Rust by default.", + "tags": [ + "immutability", + "variables", + "rust-basics" + ], + "official": false, + "year": 2023, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Naming Your Lifetimes", + "url": "https://www.possiblerust.com/pattern/naming-your-lifetimes", + "description": "Explains how using longer, declarative lifetime names can help to disambiguate which borrow is which.", + "tags": [ + "lifetimes", + "naming-conventions", + "rust-patterns" + ], + "official": false, + "year": 2021, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Aiming for idiomatic Rust", + "url": "https://web.archive.org/web/20221203043933/https://shane-o.dev/blog/aiming-for-idiomatic-rust", + "description": "Discusses different ways to solve a popular coding puzzle, 'balanced brackets', in Rust.", + "tags": [ + "coding-puzzle", + "best-practices" + ], + "official": false, + "year": 2021, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Wrapping errors in Rust", + "url": "https://edgarluque.com/blog/wrapping-errors-in-rust", + "description": "Wrapping 'reqwest::Error' and a custom error type as an enum to make library usage easier.", + "tags": [ + "error-handling", + "rust-tips", + "programming" + ], + "official": false, + "year": 2021, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Hexagonal architecture in Rust", + "url": "https://alexis-lozano.com/hexagonal-architecture-in-rust-1/", + "description": "Describes how to build a Rust service using domain driven design and a test-first approach.", + "tags": [ + "architecture", + "domain-driven-design", + "rust-service" + ], + "official": false, + "year": 2021, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Context-preserving error handling", + "url": "https://kazlauskas.me/entries/errors", + "description": "Explains how to use crates like 'thiserror' in combination with 'map_err' to add context to errors.", + "tags": [ + "error-handling", + "crates", + "rust-tips" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Refactoring Rust Transpiled from C", + "url": "https://immunant.com/blog/2020/09/transpiled_c_safety/", + "description": "Describes how to lift a C-project that was automatically converted to unsafe Rust to safer, more idiomatic Rust.", + "tags": [ + "refactoring", + "transpiling", + "c-to-rust" + ], + "official": false, + "year": 2020, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Learning Rust through open source and live code reviews", + "url": "https://loige.co/learning-rust-through-open-source-and-live-code-reviews/", + "description": "Covers patterns like 'FromStr' and exposing a CLI and a library in one crate.", + "tags": [ + "open-source", + "code-review", + "rust-patterns" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Guide on how to write documentation for a Rust crate", + "url": "https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate", + "description": "Writing good documentation with rustdoc including many examples.", + "tags": [ + "documentation", + "rustdoc", + "best-practices" + ], + "official": false, + "year": 2020, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Are out parameters idiomatic in Rust?", + "url": "https://steveklabnik.com/writing/are-out-paramters-idiomatic-in-rust", + "description": "Discusses the pros and cons of functions returning a value vs. modifying a parameter in-place.", + "tags": [ + "functions", + "parameters" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Await a minute", + "url": "https://docs.rs/dtolnay/0.0.3/dtolnay/macro._01__await_a_minute.html", + "description": "Example code for moving from raw futures to async/await syntax to improve error handling.", + "tags": [ + "async", + "await", + "error-handling" + ], + "official": false, + "year": 2019, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Taking string arguments in Rust", + "url": "http://xion.io/post/code/rust-string-args.html", + "description": "Discussing how to avoid subtle issues with string handling and when to use 'str' vs 'String'.", + "tags": [ + "strings", + "arguments", + "best-practices" + ], + "official": false, + "year": 2019, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Rust Patterns: Enums Instead Of Booleans", + "url": "http://blakesmith.me/2019/05/07/rust-patterns-enums-instead-of-booleans.html", + "description": "Discusses how using enums instead of booleans can express intent more clearly in Rust.", + "tags": [ + "enums", + "booleans", + "patterns" + ], + "official": false, + "year": 2019, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Programming an ARM microcontroller in Rust at four different levels of abstraction", + "url": "https://pramode.in/2018/02/20/programming-a-microcontroller-in-rust-at-four-levels-of-abstraction/", + "description": "Demonstrates how Rust helps to move from low-level embedded code to high-level abstractions.", + "tags": [ + "microcontroller", + "arm", + "abstraction" + ], + "official": false, + "year": 2018, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "article" + }, + { + "title": "Iteration patterns for Result & Option", + "url": "http://xion.io/post/code/rust-iter-patterns.html", + "description": "Explores how to filter and partition iterators of Result and Option types idiomatically.", + "tags": [ + "iterators", + "result", + "option" + ], + "official": false, + "year": 2017, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Lessons learned redesigning and refactoring a Rust Library", + "url": "https://web.archive.org/web/20220126172949/https://blog.mgattozzi.dev/refactor-rust/", + "description": "'RefCell', the builder pattern and more.", + "tags": [ + "refactoring", + "design-patterns", + "library" + ], + "official": false, + "year": 2017, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Math with distances in Rust: safety and correctness across units", + "url": "https://ferrisellis.com/content/rust-implementing-units-for-types/", + "description": "How to create a system to cleanly and safely do arithmetic with lengths.", + "tags": [ + "math", + "safety", + "type-system" + ], + "official": false, + "year": 2017, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "The balance between cost, useability and soundness in C bindings, and Rust-SDL2's release", + "url": "https://web.archive.org/web/20190509123207/https://cobrand.github.io/rust/sdl2/2017/05/07/the-balance-between-soundness-cost-useability.html", + "description": "Writing safe, sound, idiomatic libraries despite the limitations of the borrow checker.", + "tags": [ + "c-bindings", + "sdl2", + "borrow-checker" + ], + "official": false, + "year": 2017, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Russian Dolls and clean Rust code", + "url": "https://web.archive.org/web/20220126183049/https://blog.mgattozzi.dev/russian-dolls/", + "description": "How to use the full power of 'Option' and 'Result' (especially 'and_then()' and 'unwrap_or()').", + "tags": [ + "option", + "result", + "code-quality" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Elegant Library APIs in Rust", + "url": "https://deterministic.space/elegant-apis-in-rust.html", + "description": "Many helpful tips and tricks for writing libraries in Rust.", + "tags": [ + "libraries", + "api-design", + "best-practices" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Teaching libraries through good documentation", + "url": "https://deterministic.space/teaching-libraries.html", + "description": "How to use the full power of Rust's documentation support (e.g. doc tests).", + "tags": [ + "documentation", + "libraries" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Pretty State Machine Patterns in Rust", + "url": "https://hoverbear.org/2016/10/12/rust-state-machine-pattern/", + "description": "How to represent a State Machine in an expressive and understandable way in Rust.", + "tags": [ + "state-machine", + "patterns" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Ripgrep Code Review", + "url": "https://blog.mbrt.dev/posts/ripgrep/", + "description": "An analysis of the popular 'ripgrep' tool's source code.", + "tags": [ + "code-review", + "ripgrep", + "analysis" + ], + "official": false, + "year": 2016, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Rustic Bits", + "url": "https://llogiq.github.io/2016/02/11/rustic.html", + "description": "Small things that make for rustic code.", + "tags": [ + "best-practices", + "code-quality" + ], + "official": false, + "year": 2016, + "difficultyLevel": "beginner", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Convenient and idiomatic conversions in Rust", + "url": "https://ricardomartins.cc/2016/08/03/convenient_and_idiomatic_conversions_in_rust", + "description": "Explains 'From', 'Into', 'TryFrom', 'TryInto', 'AsRef' and 'AsMut' with practical examples.", + "tags": [ + "conversions", + "examples" + ], + "official": false, + "year": 2016, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Idiomatic tree and graph like structures in Rust", + "url": "https://rust-leipzig.github.io/architecture/2016/12/20/idiomatic-trees-in-rust/", + "description": "Introduction to safe, dynamic, arena based tree structures without using lifetimes.", + "tags": [ + "tree-structures", + "graphs" + ], + "official": false, + "year": 2016, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Rust traits for developer friendly libraries", + "url": "https://benashford.github.io/blog/2015/05/24/rust-traits-for-developer-friendly-libraries/", + "description": "Thoughts about implementing good Rust libraries.", + "tags": [ + "rust-traits", + "libraries", + "development" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "article" + }, + { + "title": "Error Handling in Rust", + "url": "https://blog.burntsushi.net/rust-error-handling/", + "description": "Understanding and handling errors in Rust in an idiomatic way.", + "tags": [ + "error-handling" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Creating a Rust function that accepts String or &str", + "url": "https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html", + "description": "How to make calling your code both ergonomic and fast (zero-allocation).", + "tags": [ + "functions", + "string-handling" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Creating a Rust function that returns a &str or String", + "url": "https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html", + "description": "How 'Into' and 'Cow' (Clone-on-write) work together to avoid allocations for string types.", + "tags": [ + "functions", + "string-handling" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Effectively Using Iterators In Rust", + "url": "https://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html", + "description": "Explanation of the 'Iter' and 'IntoIter' traits and how loops actually work in Rust.", + "tags": [ + "iterators", + "traits" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Strategies for solving 'cannot move out of' borrowing errors in Rust", + "url": "https://hermanradtke.com/2015/06/09/strategies-for-solving-cannot-move-out-of-borrowing-errors-in-rust.html", + "description": "Practical tips to help understand the borrow-checker and move semantics.", + "tags": [ + "borrow-checker", + "move-semantics" + ], + "official": false, + "year": 2015, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Rayon: data parallelism in Rust", + "url": "https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/", + "description": "Writing elegant parallel code in Rust.", + "tags": [ + "parallelism", + "rayon" + ], + "official": false, + "year": 2015, + "difficultyLevel": "advanced", + "duration": "variable", + "interactivityLevel": "medium", + "free": true, + "category": "article" + }, + { + "title": "Tricks of the Trait: Enabling Ergonomic Extractors", + "url": "https://www.youtube.com/watch?v=7DOYtnCXucw", + "description": "Rust Nation UK, Feb. 2023", + "tags": [ + "traits", + "ergonomics", + "extractors" + ], + "official": false, + "year": 2023, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Nine Rules for Elegant Rust Library APIs", + "url": "https://www.youtube.com/watch?v=6-8-9ZV-2WQ", + "description": "Seattle Rust Meetup, Sep. 2022", + "tags": [ + "library-apis", + "elegance" + ], + "official": false, + "year": 2022, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Ergonomic APIs for hard problems", + "url": "https://www.youtube.com/watch?v=Phk0C-kLlho", + "description": "RustLab Conference, October 2022", + "tags": [ + "apis", + "ergonomics", + "rust-conference" + ], + "official": false, + "year": 2022, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Macros for a More Productive Rust", + "url": "https://www.youtube.com/watch?v=dZiWkbnaQe8", + "description": "RustConf 2020", + "tags": [ + "macros", + "productivity", + "rustconf" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Making Rust Delightful", + "url": "https://www.youtube.com/watch?v=YSEx8wtlPWc", + "description": "RustCon Asia 2019", + "tags": [ + "conference", + "development" + ], + "official": false, + "year": 2019, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Idiomatic Rust - Writing Concise and Elegant Rust Code", + "url": "https://www.youtube.com/watch?v=P2mooqNMxMs", + "description": "FOSDEM 2018", + "tags": [ + "fosdem" + ], + "official": false, + "year": 2018, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Idiomatic Rust Libraries", + "url": "https://www.youtube.com/watch?v=0zOg8_B71gE", + "description": "Rustfest Kiev", + "tags": [ + "rust-libraries", + "rustfest" + ], + "official": false, + "year": 2017, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "low", + "free": true, + "category": "talk" + }, + { + "title": "Preferred way of passing `Path`-like types around?", + "url": "https://www.reddit.com/r/rust/comments/cekeq9/preferred_way_of_passing_pathlike_types_around/", + "description": "A Reddit discussion on the best practices for passing `Path`-like types in Rust.", + "tags": [ + "discussion", + "path-types", + "best-practices" + ], + "official": false, + "year": 2020, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "forum" + }, + { + "title": "Which is more idiomatic? Functional, imperative or a mix?", + "url": "https://users.rust-lang.org/t/which-is-more-idiomatic-functional-imperative-or-a-mix/11278", + "description": "A discussion on Rust's users forum about the idiomatic way to write Rust code: functional, imperative, or a mix of both.", + "tags": [ + "functional", + "imperative", + "coding-style" + ], + "official": false, + "year": 2017, + "difficultyLevel": "all", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "forum" + }, + { + "title": "An idiomatic way to sum up values in a multidimensional Array", + "url": "https://users.rust-lang.org/t/an-idiomatic-way-to-sum-up-values-in-a-multidimensional-array/9485", + "description": "Forum discussion on idiomatic approaches to summing values in a multidimensional array in Rust.", + "tags": [ + "arrays", + "summing" + ], + "official": false, + "year": 2017, + "difficultyLevel": "intermediate", + "duration": "variable", + "interactivityLevel": "high", + "free": true, + "category": "forum" + } +] \ No newline at end of file