[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: mre\n"
  },
  {
    "path": ".github/workflows/check_links.yml",
    "content": "name: Check Links\n\non:\n  push:\n  repository_dispatch:\n  workflow_dispatch:\n  schedule:\n    # Runs every Thursday at 20:23 GMT to avoid bit rot\n    - cron: \"23 20 * * 4\"\n\nenv:\n  USER_AGENT: \"linux:lychee-action:@master (by /u/mre__)\"\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v1\n\n      - name: Link Checker\n        uses: lycheeverse/lychee-action@master\n        with:\n          args: -- '*.md'\n          fail: true\n        env:\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}\n\n      - name: Create Issue From File\n        if: env.lychee_exit_code != 0\n        uses: peter-evans/create-issue-from-file@v4\n        with:\n          title: Link Checker Report\n          content-filepath: ./lychee/out.md\n          labels: report, automated issue\n\n"
  },
  {
    "path": ".github/workflows/render.yml",
    "content": "name: Render\n\non:\n  push:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    permissions:\n      # Give the default GITHUB_TOKEN write permission to commit and push the\n      # added or changed files to the repository.\n      contents: write\n\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Render list\n        run: make render\n\n      - uses: stefanzweifel/git-auto-commit-action@v5.0.0\n        if: github.event_name == 'push' && github.ref == 'refs/heads/master'\n        with:\n          commit_message: Commit list\n          commit_user_name: Idiomatic Rust Bot\n          commit_user_email: bot@idiomatic.rs\n          commit_author: Idiomatic Rust Bot <bot@idiomatic.rs>\n"
  },
  {
    "path": ".gitignore",
    "content": "# macOS-specific files\n.DS_Store\n\n# Windows-specific files\nThumbs.db\n\n# Generated by Cargo\n/target/\ndebug/\n\n# Generated by snapcraft\n*.snap\n\n# NOTE: Cargo.lock should be committed for workspaces with both binaries and libraries\n# Cargo.lock\n\n# Backup files generated by rustfmt\n**/*.rs.bk\n\n# IDE-specific files and directories\n.idea/\n.vscode/\n.zed/\n\n"
  },
  {
    "path": ".lycheeignore",
    "content": "linkedin.com\nreddit.com\nfreepik.com\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Idiomatic Rust\n\n## Introduction\n\nThank you for your interest in contributing to Idiomatic Rust! This guide will\nhelp you understand how to contribute effectively.\n\n## `README` is Auto-Generated\n\nPlease note that the `README.md` file in this repository is auto-generated\n*using a\nRust script. **Do not edit the `README.md` file directly.** Instead, make\nchanges to the `resources.json` file or the Rust script.\n\n### Generating the README\n\nTo generate the README, ensure that Rust is installed on your machine. You can\nthen run the following command:\n\n```sh\nmake render\n```\n\nThis will update the `README.md` file based on the current contents of\n`resources.json`.\n\n### Adding Resources to `resources.json`\n\n`resources.json` is the primary file where resources about idiomatic Rust are\nlisted. The file is structured in a JSON array, where each resource is an object\nwith specific fields.\n\n### File Structure\n\nEach resource object in `resources.json` should have the following structure:\n\n```json\n{\n  \"title\": \"Resource Title\",\n  \"url\": \"https://resource.url\",\n  \"description\": \"A brief description of the resource.\",\n  \"tags\": [\"tag1\", \"tag2\"],\n  \"official\": true or false,\n  \"year\": YearOfPublication,\n  \"difficultyLevel\": \"beginner | intermediate | advanced\",\n  \"duration\": \"time duration (if audio/video) or null\",\n  \"interactivityLevel\": \"low | medium | high\",\n  \"free\": true or false,\n  \"category\": \"project | workshop | book | article | talk | forum\"\n}\n```\n\nCheck out the file for some examples.\nPlease ensure that your addition adheres to this format for consistency.\n\n### Adding a New Resource\n\n1. Fork the repository.\n2. Add your resource to `resources.json`, following the structure above.\n3. Run `make render` to locally to generate the README.\n4. Create a pull request with your changes.\n\n### Pull Requests\n\nWhen you submit a pull request, please include the following:\n\n* A brief explanation of the resource and why it's beneficial for idiomatic\n  Rust.\n* Confirmation that the resource links and information are current and valid.\n\n### Questions or Issues\n\nIf you have any questions or encounter any issues, please open an issue in the\nrepository, and we'll get back to you as soon as possible.\n\nThank you for contributing to making Rust programming more idiomatic and\naccessible!\n"
  },
  {
    "path": "Makefile",
    "content": ".PHONY: render\nrender:\n\tcargo run --manifest-path=render/Cargo.toml"
  },
  {
    "path": "README.md",
    "content": "<!--\n⚠️⚠️ WARNING: This file is generated by `make render`. Do not edit manually!\nSee `CONTRIBUTING.md` for more information.\n-->\n\n<picture >\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"assets/idiomatic-rust-dark.png\">\n  <img src=\"assets/idiomatic-rust.png\" />\n</picture>\n\n[![Check Links](https://github.com/mre/idiomatic-rust/workflows/Check%20Links/badge.svg)](https://github.com/mre/idiomatic-rust/actions/workflows/check_links.yml)\n\nThis repository collects resources for writing clean, idiomatic Rust code.\nYou can find a sortable/searchable version of this list [here](https://corrode.dev/idiomatic-rust/).\n\n> _Idiomatic_ coding means following the conventions of a given language. It is\n> the most concise, convenient, and common way of accomplishing a task in that\n> language, rather than forcing it to work in a way the author is familiar with\n> from a different language. - Adapted from [Tim\n> Mansfield](https://github.com/tim-hr/stuff/wiki/Idiomatic-coding)\n\nContributions welcome! To add missing resources, [please refer to the contributing documentation](https://github.com/mre/idiomatic-rust/blob/master/CONTRIBUTING.md).\n\n## ⚙ Projects\n\n- [blessed.rs](https://blessed.rs/crates) — An unofficial guide to the Rust ecosystem. Suggestions for popular, well-maintained crates.\n- [Canonical's Rust Best Practices](https://canonical.github.io/rust-best-practices/) — A curated collection of best practices for writing Rust code, covering coding standards from naming conventions to unsafe code usage.\n- [cheats.rs - Idiomatic Rust tips](https://cheats.rs/) — A list of quick tips to make your code more idiomatic.\n- [clippy](https://github.com/rust-lang/rust-clippy) — A bunch of lints to catch common mistakes and improve your Rust code.\n- [Elements of Rust](https://github.com/ferrous-systems/elements-of-rust) — A collection of software engineering techniques for effectively expressing intent with Rust.\n- [Patterns](https://rust-unofficial.github.io/patterns/) — A catalogue of design patterns in Rust.\n- [Possible Rust](https://www.possiblerust.com/) — A blog for intermediate Rust programmers exploring real-world code and design patterns.\n- [Rust Anthology](https://github.com/brson/rust-anthology) — The best short-form writing about Rust, collected.\n- [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/) — An extensive list of recommendations for idiomatic Rust APIs.\n- [Rust by Example](https://doc.rust-lang.org/rust-by-example/) — A community driven collection of example code which follow Rust best practices.\n\n\n## 🏋 Workshops\n\n- [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!\n- [Comprehensive Rust](https://github.com/google/comprehensive-rust) — A four day Rust course developed by the Android team, covering all aspects of Rust.\n- [Ferrous Systems Teaching Material](https://ferrous-systems.github.io/teaching-material/index.html) — Free workshop material produced by Ferrous Systems for trainings.\n- [Hecto: Build your own text editor in Rust](https://philippflenker.com/hecto/) — This is a series of blog posts that shows you how to build a text editor in Rust\n- [Idiomatic Rust Workshop](https://fettblog.eu/slides/idiomatic-rust/) — A talk/workshop about idiomatic Rust code focusing on effective use of existing syntax and design patterns\n- [PingCAP talent plan](https://github.com/pingcap/talent-plan) — A series of training courses about writing distributed systems in Rust.\n- [Procedural Macros Workshop](https://github.com/dtolnay/proc-macro-workshop) — A selection of projects designed to learn to write Rust procedural macros.\n- [Rust 101](https://teach-rs.trifectatech.org/) — A Rust University course by tweede golf.\n- [Rust Development at Sentry](https://develop.sentry.dev/engineering-practices/rust/) — A document containing useful resources for getting started with Rust and adhering to Sentry coding principles.\n- [rust-lang/rustlings](https://github.com/rust-lang/rustlings) — Small exercises to get you used to reading and writing Rust code.\n\n\n## 📖 Books\n\n- [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.\n- [Command-Line Rust](https://github.com/kyclark/command-line-rust) — Learn the language by writing Rust versions of common Unix coreutils.\n- [Discover the world of microcontrollers through Rust!](https://docs.rust-embedded.org/discovery/) — An introductory course on microcontroller-based embedded systems using Rust.\n- [High Assurance Rust](https://highassurance.rs/) — Developing secure and robust software, focusing on embedded-friendly data structures in Rust.\n- [Idiomatic Rust Snippets](https://idiomatic-rust-snippets.org/) — Beginner-friendly guide to core Rust concepts—one of the best cheat sheets for Rust developers.\n- [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.\n- [Rust Atomics and Locks](https://marabos.nl/atomics/) — Helps Rust programmers of all levels gain a clear understanding of low-level concurrency.\n- [Rust Cookbook](https://github.com/rust-lang-nursery/rust-cookbook) — Examples that demonstrate good practices to accomplish common programming tasks in Rust.\n- [Rust for Rustaceans](https://nostarch.com/rust-rustaceans) — Covers how to design reliable, idiomatic, and ergonomic Rust programs based on best principles.\n\n\n## 📰 Articles\n\n### 2025\n\n- [Level Up your Rust pattern matching](https://blog.cuongle.dev/p/level-up-your-rust-pattern-matching) — Advanced pattern matching techniques and idiomatic usage.\n- [Be Simple](https://corrode.dev/blog/simple/) — Advocates for simpler, more maintainable code in Rust.\n- [Pitfalls of Safe Rust](https://corrode.dev/blog/pitfalls-of-safe-rust/) — Essential guide to avoiding pitfalls even in safe Rust code.\n- [Flattening Rust's Learning Curve](https://corrode.dev/blog/flattening-rusts-learning-curve/) — Best practices for learning Rust and reducing adoption friction.\n- [Patterns for Defensive Programming in Rust](https://corrode.dev/blog/defensive-programming/) — Defensive coding in Rust with best practices.\n- [Prototyping in Rust](https://corrode.dev/blog/prototyping/) — Rapid development methodology and idiomatic practices showing how to prototype effectively in Rust.\n- [Cancelling async Rust](https://sunshowers.io/posts/cancelling-async-rust/) — Guide to cancellation safety in async Rust with patterns for resource management.\n- [To panic or not to panic](https://www.ncameron.org/blog/to-panic-or-not-to-panic/) — Error handling strategies and when panicking is appropriate versus returning Result types.\n- [Designing Error Types in Rust Libraries](https://d34dl0ck.me/rust-bites-designing-error-types-in-rust-libraries/index.html) — Approaches to structuring error handling in library APIs for clarity and usability.\n### 2024\n\n- [The Mediocre Programmer's Guide to Rust](https://www.hezmatt.org/~mpalmer/blog/2024/05/01/the-mediocre-programmers-guide-to-rust.html) — Practical Rust without perfectionism - a pragmatic development approach.\n- [Rust's Sneaky Deadlock With if let Blocks](https://brooksblog.bearblog.dev/rusts-sneaky-deadlock-with-if-let-blocks/) — Subtle lock holding pattern that can cause critical deadlock pitfalls.\n- [Rust Iterators Beyond the Basics](https://blog.jetbrains.com/rust/2024/03/12/rust-iterators-beyond-the-basics-part-i-building-blocks/) — Advanced iterator patterns for functional programming in Rust.\n- [The Ultimate Guide to Rust Newtypes](https://www.howtocodeit.com/articles/ultimate-guide-rust-newtypes) — Using newtypes for type safety and compile-time domain validation.\n- [How to Build Abstractions in Rust Applications](https://orodu.net/2023/12/27/rust-abstractions.html) — Building effective abstractions in Rust based on software design principles.\n- [Don't Worry About Lifetimes](https://corrode.dev/blog/lifetimes/) — Demystifying lifetime annotations with practical lifetime management patterns.\n- [When should I use String vs &str?](https://steveklabnik.com/writing/when-should-i-use-string-vs-str/) — Guidance on choosing the right string type - a fundamental idiomatic Rust pattern.\n- [Async Rust can be a pleasure to work with (without Send + Sync + 'static)](https://emschwartz.me/async-rust-can-be-a-pleasure-to-work-with-without-send-sync-static/) — Relaxing trait bounds for simpler async code and ergonomic async patterns for single-threaded contexts.\n- [Why choose async/await over threads?](https://notgull.net/why-not-threads/) — Guidance on when to use async vs traditional threading to choose the right concurrency model.\n- [Three Kinds Of Unwrap](https://zkrising.com/writing/three-unwraps/) — Understanding when and how to use different unwrap variants to prevent common panic-related bugs.\n- [Practical guide to Error Handling in Rust](https://dev-state.com/posts/error_handling/) — Hands-on guide with practical examples for common error handling scenarios in real-world applications.\n### 2023\n\n- [Aim For Immutability in Rust](https://corrode.dev/blog/immutability/) — Explains why variables are immutable in Rust by default.\n- [Compile-Time Invariants in Rust](https://corrode.dev/blog/compile-time-invariants/) — Shows how macros can be used to enforce invariants at compile-time.\n### 2021\n\n- [Rust Number Conversion: Don't Follow the Book...](https://blog.notmet.net/2021/12/rust-number-conversion-dont-follow-the-book.../) — A blog post discussing the best practices for number conversion in Rust.\n- [Hexagonal architecture in Rust](https://alexis-lozano.com/blog/hexagonal-architecture-in-rust-1/) — Describes how to build a Rust service using domain driven design and a test-first approach.\n- [Wrapping errors in Rust](https://edgl.dev/blog/wrapping-errors-in-rust/) — Wrapping 'reqwest::Error' and a custom error type as an enum to make library usage easier.\n- [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.\n- [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.\n### 2020\n\n- [Are out parameters idiomatic in Rust?](https://steveklabnik.com/writing/are-out-parameters-idiomatic-in-rust/) — Discusses the pros and cons of functions returning a value vs. modifying a parameter in-place.\n- [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.\n- [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.\n- [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.\n- [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.\n### 2019\n\n- [Rust Patterns: Enums Instead Of Booleans](https://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.\n- [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'.\n- [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.\n### 2018\n\n- [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.\n### 2017\n\n- [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.\n- [Math with distances in Rust: safety and correctness across units](https://www.ferrisellis.com/content/rust-implementing-units-for-types/) — How to create a system to cleanly and safely do arithmetic with lengths.\n- [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.\n- [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.\n### 2016\n\n- [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.\n- [Convenient and idiomatic conversions in Rust](https://ricardomartins.cc/2016/08/03/convenient_and_idiomatic_conversions_in_rust) — Explains 'From<T>', 'Into<T>', 'TryFrom<T>', 'TryInto<T>', 'AsRef<T>' and 'AsMut<T>' with practical examples.\n- [Rustic Bits](https://llogiq.github.io/2016/02/11/rustic.html) — Small things that make for rustic code.\n- [Ripgrep Code Review](https://blog.mbrt.dev/posts/ripgrep/) — An analysis of the popular 'ripgrep' tool's source code.\n- [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.\n- [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).\n- [Elegant Library APIs in Rust](https://deterministic.space/elegant-apis-in-rust.html) — Many helpful tips and tricks for writing libraries in Rust.\n- [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()').\n### 2015\n\n- [Rayon: data parallelism in Rust](https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/) — Writing elegant parallel code in Rust.\n- [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.\n- [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.\n- [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.\n- [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).\n- [Error Handling in Rust](https://burntsushi.net/rust-error-handling/) — Understanding and handling errors in Rust in an idiomatic way.\n- [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.\n\n\n## 🎤 Talks\n\n### 2024\n\n- The Four Horsemen of Bad Rust Code — A talk about common pitfalls in Rust code like overengineering and premature optimization. [[Video](https://github.com/corrode/four-horsemen-talk)]\n### 2023\n\n- Tricks of the Trait: Enabling Ergonomic Extractors — Rust Nation UK, Feb. 2023 [[Video](https://www.youtube.com/watch?v=7DOYtnCXucw)]\n### 2022\n\n- Ergonomic APIs for hard problems — RustLab Conference, October 2022 [[Video](https://www.youtube.com/watch?v=Phk0C-kLlho)]\n- Nine Rules for Elegant Rust Library APIs — Seattle Rust Meetup, Sep. 2022 [[Video](https://www.youtube.com/watch?v=6-8-9ZV-2WQ)]\n### 2020\n\n- Macros for a More Productive Rust — RustConf 2020 [[Video](https://www.youtube.com/watch?v=dZiWkbnaQe8)]\n### 2019\n\n- Making Rust Delightful — RustCon Asia 2019 [[Video](https://www.youtube.com/watch?v=YSEx8wtlPWc)]\n### 2018\n\n- Idiomatic Rust - Writing Concise and Elegant Rust Code — FOSDEM 2018 [[Video](https://www.youtube.com/watch?v=P2mooqNMxMs)]\n### 2017\n\n- Idiomatic Rust Libraries — Rustfest Kiev [[Video](https://www.youtube.com/watch?v=0zOg8_B71gE)]\n\n\n## 💬 Forum\n\n### 2020\n\n- [Preferred way of passing `Path`-like types around?](https://www.reddit.com/r/rust/comments/cekeq9/preferred_way_of_passing_pathlike_types_around/)\n### 2017\n\n- [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)\n- [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)\n\n\n## 📜 History\n\nComing 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://peps.python.org/pep-0020/). For Rust, there is no such thing as the Zen of Python, however, so I started collecting my own resources.\nThe 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.\n\n## 🔏 License\n\n[![CC0](https://licensebuttons.net/p/zero/1.0/88x31.png)](https://creativecommons.org/publicdomain/zero/1.0/)\n\nTo the extent possible under law, [Matthias Endler](https://endler.dev) has waived all copyright and related or neighboring rights to this work.\nLogo adapted from [FreePik.com](https://www.freepik.com)."
  },
  {
    "path": "render/.gitignore",
    "content": "target/"
  },
  {
    "path": "render/Cargo.toml",
    "content": "[package]\nname = \"render\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\naskama = \"0.12.1\"\nindexmap = \"2.13.0\"\nitertools = \"0.12.1\"\nserde = { version = \"1.0.228\", features = [\"serde_derive\"] }\nserde_json = \"1.0.149\"\nurl = { version = \"2.5.8\", features = [\"serde\"] }\n"
  },
  {
    "path": "render/src/main.rs",
    "content": "use std::fs;\n\nuse askama::Template;\nuse indexmap::IndexMap;\nuse itertools::Itertools;\nuse serde::{Deserialize, Deserializer, Serialize};\nuse url::Url;\n\n#[derive(Template)]\n#[template(path = \"README.md\")]\nstruct ReadmeTemplate {\n    projects: Vec<Resource>,\n    workshops: Vec<Resource>,\n    books: Vec<Resource>,\n    articles: YearMap,\n    talks: YearMap,\n    forum: YearMap,\n}\n\n/// A tag is a special kind of string that\n/// - is lowercase\n/// - has no whitespace\n/// - has no special characters except for `-`\n/// - has no leading or trailing `-`\n/// - has no consecutive `-`\n/// - has no more than 50 characters\n/// - is not empty\n/// - only contains ASCII characters\n/// - does not contain numbers\n#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]\nstruct Tag(String);\n\nimpl TryFrom<String> for Tag {\n    type Error = String;\n\n    fn try_from(value: String) -> Result<Self, Self::Error> {\n        if value.is_empty() {\n            return Err(\"Tag cannot be empty\".to_string());\n        }\n\n        if value.len() > 50 {\n            return Err(format!(\n                \"Tag '{value}' cannot be longer than 50 characters (length: {})\",\n                value.len()\n            ));\n        }\n\n        if value.contains(|c: char| !c.is_ascii_lowercase() && c != '-') {\n            return Err(format!(\n                \"Tag '{value}' can only contain lowercase ASCII characters and hyphens\"\n            ));\n        }\n\n        if value.contains(|c: char| c.is_ascii_digit()) {\n            return Err(format!(\"Tag '{value}' cannot contain numbers\"));\n        }\n\n        if value.contains(|c: char| !c.is_ascii() && c != '-') {\n            return Err(format!(\n                \"Tag '{value}' can only contain ASCII characters and hyphens\"\n            ));\n        }\n\n        if value.starts_with('-') || value.ends_with('-') {\n            return Err(format!(\n                \"Tag '{value}' cannot start or end with a hyphen\"\n            ));\n        }\n\n        if value.contains(\"--\") {\n            return Err(format!(\n                \"Tag '{value}' cannot contain consecutive hyphens\"\n            ));\n        }\n\n        if value.contains(char::is_whitespace) {\n            return Err(format!(\"Tag '{value}' cannot contain whitespace\"));\n        }\n\n        Ok(Tag(value))\n    }\n}\n\nimpl<'de> Deserialize<'de> for Tag {\n    fn deserialize<D>(deserializer: D) -> Result<Tag, D::Error>\n    where\n        D: Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        Tag::try_from(s).map_err(serde::de::Error::custom)\n    }\n}\n\n#[derive(Debug, Deserialize, Clone, Serialize)]\nenum Difficulty {\n    #[serde(rename = \"all\")]\n    All,\n    #[serde(rename = \"beginner\")]\n    Beginner,\n    #[serde(rename = \"intermediate\")]\n    Intermediate,\n    #[serde(rename = \"advanced\")]\n    Advanced,\n}\n\n#[derive(Debug, Deserialize, Clone, Serialize)]\nenum InteractivityLevel {\n    #[serde(rename = \"low\")]\n    Low,\n    #[serde(rename = \"medium\")]\n    Medium,\n    #[serde(rename = \"high\")]\n    High,\n}\n\n#[derive(Debug, Deserialize, Clone, Serialize, Eq, PartialEq, Ord, PartialOrd)]\nenum Category {\n    #[serde(rename = \"project\")]\n    Project,\n    #[serde(rename = \"workshop\")]\n    Workshop,\n    #[serde(rename = \"book\")]\n    Book,\n    #[serde(rename = \"article\")]\n    Article,\n    #[serde(rename = \"talk\")]\n    Talk,\n    #[serde(rename = \"forum\")]\n    Forum,\n}\n\n#[allow(dead_code)]\n#[derive(Debug, Deserialize, Clone)]\nstruct Resource {\n    title: String,\n    url: Url,\n    description: String,\n    tags: Vec<Tag>,\n    official: bool,\n    year: usize,\n    #[serde(rename = \"difficultyLevel\")]\n    difficulty_level: Difficulty,\n    duration: Option<String>,\n    #[serde(rename = \"interactivityLevel\")]\n    interactivity_level: InteractivityLevel,\n    free: bool,\n    category: Category,\n}\n\ntype Resources = Vec<Resource>;\n\ntype YearMap = IndexMap<usize, Resources>;\n\nfn group_by_year(resources: &Resources, category: Category) -> YearMap {\n    resources\n        .iter()\n        .filter(|r| r.category == category)\n        .sorted_by_key(|r| r.year)\n        .rev()\n        .fold(YearMap::new(), |mut map, r| {\n            map.entry(r.year).or_insert_with(Vec::new).push(r.clone());\n            map\n        })\n}\n\nfn sort_by_title(resources: &Resources, category: Category) -> Resources {\n    resources\n        .iter()\n        .filter(|r| r.category == category)\n        .sorted_by_key(|r| r.title.to_lowercase())\n        .cloned()\n        .collect()\n}\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    let file = std::fs::File::open(\"resources.json\")?;\n    let resources: Resources = serde_json::from_reader(file)?;\n\n    let readme = ReadmeTemplate {\n        projects: sort_by_title(&resources, Category::Project),\n        workshops: sort_by_title(&resources, Category::Workshop),\n        books: sort_by_title(&resources, Category::Book),\n        articles: group_by_year(&resources, Category::Article),\n        talks: group_by_year(&resources, Category::Talk),\n        forum: group_by_year(&resources, Category::Forum),\n    };\n\n    fs::write(\"README.md\", readme.render()?)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "render/templates/README.md",
    "content": "<!--\n⚠️⚠️ WARNING: This file is generated by `make render`. Do not edit manually!\nSee `CONTRIBUTING.md` for more information.\n-->\n\n<picture >\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"assets/idiomatic-rust-dark.png\">\n  <img src=\"assets/idiomatic-rust.png\" />\n</picture>\n\n[![Check Links](https://github.com/mre/idiomatic-rust/workflows/Check%20Links/badge.svg)](https://github.com/mre/idiomatic-rust/actions/workflows/check_links.yml)\n\nThis repository collects resources for writing clean, idiomatic Rust code.\nYou can find a sortable/searchable version of this list [here](https://corrode.dev/idiomatic-rust/).\n\n> _Idiomatic_ coding means following the conventions of a given language. It is\n> the most concise, convenient, and common way of accomplishing a task in that\n> language, rather than forcing it to work in a way the author is familiar with\n> from a different language. - Adapted from [Tim\n> Mansfield](https://github.com/tim-hr/stuff/wiki/Idiomatic-coding)\n\nContributions welcome! To add missing resources, [please refer to the contributing documentation](https://github.com/mre/idiomatic-rust/blob/master/CONTRIBUTING.md).\n\n## ⚙ Projects\n\n{% for project in projects -%}\n- [{{ project.title }}]({{ project.url }}) — {{ project.description }}\n{% endfor %}\n\n## 🏋 Workshops\n\n{% for workshop in workshops -%}\n- [{{ workshop.title }}]({{ workshop.url }}) — {{ workshop.description }}\n{% endfor %}\n\n## 📖 Books\n\n{% for book in books -%}\n- [{{ book.title }}]({{ book.url }}) — {{ book.description }}\n{% endfor %}\n\n## 📰 Articles\n\n{% for (year, resources) in articles -%}\n\n### {{ year }}\n\n{% for resource in resources -%}\n- [{{ resource.title }}]({{ resource.url }}) — {{ resource.description }}\n{% endfor %}\n{%- endfor %}\n\n## 🎤 Talks\n\n{% for (year, resources) in talks -%}\n\n### {{ year }}\n\n{% for resource in resources -%}\n- {{ resource.title }} — {{ resource.description }} [[Video]({{ resource.url }})]\n{% endfor %}\n{%- endfor %}\n\n## 💬 Forum\n\n{% for (year, resources) in forum -%}\n\n### {{ year }}\n\n{% for resource in resources -%}\n- [{{ resource.title }}]({{ resource.url }})\n{% endfor %}\n{%- endfor %}\n\n## 📜 History\n\nComing 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://peps.python.org/pep-0020/). For Rust, there is no such thing as the Zen of Python, however, so I started collecting my own resources.\nThe 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.\n\n## 🔏 License\n\n[![CC0](https://licensebuttons.net/p/zero/1.0/88x31.png)](https://creativecommons.org/publicdomain/zero/1.0/)\n\nTo the extent possible under law, [Matthias Endler](https://endler.dev) has waived all copyright and related or neighboring rights to this work.\nLogo adapted from [FreePik.com](https://www.freepik.com).\n"
  },
  {
    "path": "resources.json",
    "content": "[\n  {\n    \"title\": \"Rust Anthology\",\n    \"url\": \"https://github.com/brson/rust-anthology\",\n    \"description\": \"The best short-form writing about Rust, collected.\",\n    \"tags\": [\"anthology\", \"writing\", \"collection\"],\n    \"official\": false,\n    \"year\": 2018,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"blessed.rs\",\n    \"url\": \"https://blessed.rs/crates\",\n    \"description\": \"An unofficial guide to the Rust ecosystem. Suggestions for popular, well-maintained crates.\",\n    \"tags\": [\"guide\", \"ecosystem\", \"crates\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Canonical's Rust Best Practices\",\n    \"url\": \"https://canonical.github.io/rust-best-practices/\",\n    \"description\": \"A curated collection of best practices for writing Rust code, covering coding standards from naming conventions to unsafe code usage.\",\n    \"tags\": [\"best-practices\", \"coding-standards\", \"guide\"],\n    \"official\": true,\n    \"year\": 2025,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"cheats.rs - Idiomatic Rust tips\",\n    \"url\": \"https://cheats.rs\",\n    \"description\": \"A list of quick tips to make your code more idiomatic.\",\n    \"tags\": [\"tips\", \"idiomatic\", \"quick\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"clippy\",\n    \"url\": \"https://github.com/rust-lang/rust-clippy\",\n    \"description\": \"A bunch of lints to catch common mistakes and improve your Rust code.\",\n    \"tags\": [\"lints\", \"code-quality\", \"tool\"],\n    \"official\": true,\n    \"year\": 2015,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Patterns\",\n    \"url\": \"https://rust-unofficial.github.io/patterns/\",\n    \"description\": \"A catalogue of design patterns in Rust.\",\n    \"tags\": [\"design-patterns\", \"catalogue\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Elements of Rust\",\n    \"url\": \"https://github.com/ferrous-systems/elements-of-rust\",\n    \"description\": \"A collection of software engineering techniques for effectively expressing intent with Rust.\",\n    \"tags\": [\"software-engineering\", \"techniques\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Possible Rust\",\n    \"url\": \"https://www.possiblerust.com/\",\n    \"description\": \"A blog for intermediate Rust programmers exploring real-world code and design patterns.\",\n    \"tags\": [\"blog\", \"intermediate\", \"design-patterns\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Rust API Guidelines\",\n    \"url\": \"https://rust-lang.github.io/api-guidelines/\",\n    \"description\": \"An extensive list of recommendations for idiomatic Rust APIs.\",\n    \"tags\": [\"api\", \"guidelines\", \"best-practices\"],\n    \"official\": true,\n    \"year\": 2017,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Rust by Example\",\n    \"url\": \"https://doc.rust-lang.org/rust-by-example/\",\n    \"description\": \"A community driven collection of example code which follow Rust best practices.\",\n    \"tags\": [\"examples\", \"community\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"project\"\n  },\n  {\n    \"title\": \"Comprehensive Rust\",\n    \"url\": \"https://github.com/google/comprehensive-rust\",\n    \"description\": \"A four day Rust course developed by the Android team, covering all aspects of Rust.\",\n    \"tags\": [\"course\", \"learning\", \"comprehensive\"],\n    \"official\": true,\n    \"year\": 2021,\n    \"difficultyLevel\": \"all\",\n    \"duration\": \"4 days\",\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Hecto: Build your own text editor in Rust\",\n    \"url\": \"https://philippflenker.com/hecto/\",\n    \"description\": \"This is a series of blog posts that shows you how to build a text editor in Rust\",\n    \"tags\": [\"project\", \"learning\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"all\",\n    \"duration\": \"variable\",\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Build your own JIRA with Rust\",\n    \"url\": \"https://github.com/LukeMathWalker/build-your-own-jira-with-rust/\",\n    \"description\": \"A test-driven workshop to learn Rust by building your own JIRA clone!\",\n    \"tags\": [\"test-driven\", \"project\"],\n    \"official\": true,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Ferrous Systems Teaching Material\",\n    \"url\": \"https://ferrous-systems.github.io/teaching-material/index.html\",\n    \"description\": \"Free workshop material produced by Ferrous Systems for trainings.\",\n    \"tags\": [\"material\", \"training\"],\n    \"official\": true,\n    \"year\": 2019,\n    \"difficultyLevel\": \"all\",\n    \"duration\": \"3-4 days\",\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"PingCAP talent plan\",\n    \"url\": \"https://github.com/pingcap/talent-plan\",\n    \"description\": \"A series of training courses about writing distributed systems in Rust.\",\n    \"tags\": [\"training\", \"distributed-systems\", \"course\"],\n    \"official\": true,\n    \"year\": 2018,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Procedural Macros Workshop\",\n    \"url\": \"https://github.com/dtolnay/proc-macro-workshop\",\n    \"description\": \"A selection of projects designed to learn to write Rust procedural macros.\",\n    \"tags\": [\"macros\", \"coding\"],\n    \"official\": true,\n    \"year\": 2019,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"rust-lang/rustlings\",\n    \"url\": \"https://github.com/rust-lang/rustlings\",\n    \"description\": \"Small exercises to get you used to reading and writing Rust code.\",\n    \"tags\": [\"exercises\", \"learning\", \"beginner\"],\n    \"official\": true,\n    \"year\": 2018,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Rust Development at Sentry\",\n    \"url\": \"https://develop.sentry.dev/engineering-practices/rust/\",\n    \"description\": \"A document containing useful resources for getting started with Rust and adhering to Sentry coding principles.\",\n    \"tags\": [\"guide\", \"coding-principles\", \"development\"],\n    \"official\": true,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Rust 101\",\n    \"url\": \"https://teach-rs.trifectatech.org/\",\n    \"description\": \"A Rust University course by tweede golf.\",\n    \"tags\": [\"course\", \"university\", \"learning\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Command Line Applications in Rust\",\n    \"url\": \"https://rust-cli.github.io/book/\",\n    \"description\": \"A tutorial on how to write CLI apps in Rust, learning many aspects of the ecosystem.\",\n    \"tags\": [\"tutorial\", \"cli\", \"ecosystem\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Command-Line Rust\",\n    \"url\": \"https://github.com/kyclark/command-line-rust\",\n    \"description\": \"Learn the language by writing Rust versions of common Unix coreutils.\",\n    \"tags\": [\"unix\", \"coreutils\", \"learning\"],\n    \"official\": false,\n    \"year\": 2022,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Discover the world of microcontrollers through Rust!\",\n    \"url\": \"https://docs.rust-embedded.org/discovery/\",\n    \"description\": \"An introductory course on microcontroller-based embedded systems using Rust.\",\n    \"tags\": [\"embedded-systems\", \"microcontroller\", \"course\"],\n    \"official\": false,\n    \"year\": 2023,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"High Assurance Rust\",\n    \"url\": \"https://highassurance.rs/\",\n    \"description\": \"Developing secure and robust software, focusing on embedded-friendly data structures in Rust.\",\n    \"tags\": [\"security\", \"robustness\", \"embedded\"],\n    \"official\": false,\n    \"year\": 2022,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Idiomatic Rust Snippets\",\n    \"url\": \"https://idiomatic-rust-snippets.org\",\n    \"description\": \"Beginner-friendly guide to core Rust concepts—one of the best cheat sheets for Rust developers.\",\n    \"tags\": [\"patterns\", \"idiomatic\", \"snippets\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Rust Cookbook\",\n    \"url\": \"https://github.com/rust-lang-nursery/rust-cookbook\",\n    \"description\": \"Examples that demonstrate good practices to accomplish common programming tasks in Rust.\",\n    \"tags\": [\"examples\", \"good-practices\", \"programming\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Rust for Rustaceans\",\n    \"url\": \"https://nostarch.com/rust-rustaceans\",\n    \"description\": \"Covers how to design reliable, idiomatic, and ergonomic Rust programs based on best principles.\",\n    \"tags\": [\"design\", \"idiomatic\", \"ergonomic\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": false,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Programming Rust: Fast, Safe Systems Development\",\n    \"url\": \"https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/\",\n    \"description\": \"A comprehensive Rust Programming Guide that covers most of Rust's features in detail.\",\n    \"tags\": [\"comprehensive\", \"features\", \"guide\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": false,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Rust Atomics and Locks\",\n    \"url\": \"https://marabos.nl/atomics/\",\n    \"description\": \"Helps Rust programmers of all levels gain a clear understanding of low-level concurrency.\",\n    \"tags\": [\"concurrency\", \"low-level\", \"understanding\"],\n    \"official\": false,\n    \"year\": 2023,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"book\"\n  },\n  {\n    \"title\": \"Compile-Time Invariants in Rust\",\n    \"url\": \"https://corrode.dev/blog/compile-time-invariants/\",\n    \"description\": \"Shows how macros can be used to enforce invariants at compile-time.\",\n    \"tags\": [\"macros\", \"invariants\", \"compile-time\"],\n    \"official\": false,\n    \"year\": 2023,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Aim For Immutability in Rust\",\n    \"url\": \"https://corrode.dev/blog/immutability/\",\n    \"description\": \"Explains why variables are immutable in Rust by default.\",\n    \"tags\": [\"immutability\", \"variables\", \"rust-basics\"],\n    \"official\": false,\n    \"year\": 2023,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Naming Your Lifetimes\",\n    \"url\": \"https://www.possiblerust.com/pattern/naming-your-lifetimes\",\n    \"description\": \"Explains how using longer, declarative lifetime names can help to disambiguate which borrow is which.\",\n    \"tags\": [\"lifetimes\", \"naming-conventions\", \"rust-patterns\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Aiming for idiomatic Rust\",\n    \"url\": \"https://web.archive.org/web/20221203043933/https://shane-o.dev/blog/aiming-for-idiomatic-rust\",\n    \"description\": \"Discusses different ways to solve a popular coding puzzle, 'balanced brackets', in Rust.\",\n    \"tags\": [\"coding-puzzle\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Wrapping errors in Rust\",\n    \"url\": \"https://edgl.dev/blog/wrapping-errors-in-rust/\",\n    \"description\": \"Wrapping 'reqwest::Error' and a custom error type as an enum to make library usage easier.\",\n    \"tags\": [\"error-handling\", \"rust-tips\", \"programming\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Hexagonal architecture in Rust\",\n    \"url\": \"https://alexis-lozano.com/blog/hexagonal-architecture-in-rust-1/\",\n    \"description\": \"Describes how to build a Rust service using domain driven design and a test-first approach.\",\n    \"tags\": [\"architecture\", \"domain-driven-design\", \"rust-service\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Context-preserving error handling\",\n    \"url\": \"https://kazlauskas.me/entries/errors\",\n    \"description\": \"Explains how to use crates like 'thiserror' in combination with 'map_err' to add context to errors.\",\n    \"tags\": [\"error-handling\", \"crates\", \"rust-tips\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Refactoring Rust Transpiled from C\",\n    \"url\": \"https://immunant.com/blog/2020/09/transpiled_c_safety/\",\n    \"description\": \"Describes how to lift a C-project that was automatically converted to unsafe Rust to safer, more idiomatic Rust.\",\n    \"tags\": [\"refactoring\", \"transpiling\", \"c-to-rust\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Learning Rust through open source and live code reviews\",\n    \"url\": \"https://loige.co/learning-rust-through-open-source-and-live-code-reviews/\",\n    \"description\": \"Covers patterns like 'FromStr' and exposing a CLI and a library in one crate.\",\n    \"tags\": [\"open-source\", \"code-review\", \"rust-patterns\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Guide on how to write documentation for a Rust crate\",\n    \"url\": \"https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate\",\n    \"description\": \"Writing good documentation with rustdoc including many examples.\",\n    \"tags\": [\"documentation\", \"rustdoc\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Are out parameters idiomatic in Rust?\",\n    \"url\": \"https://steveklabnik.com/writing/are-out-parameters-idiomatic-in-rust/\",\n    \"description\": \"Discusses the pros and cons of functions returning a value vs. modifying a parameter in-place.\",\n    \"tags\": [\"functions\", \"parameters\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Await a minute\",\n    \"url\": \"https://docs.rs/dtolnay/0.0.3/dtolnay/macro._01__await_a_minute.html\",\n    \"description\": \"Example code for moving from raw futures to async/await syntax to improve error handling.\",\n    \"tags\": [\"async\", \"await\", \"error-handling\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Taking string arguments in Rust\",\n    \"url\": \"http://xion.io/post/code/rust-string-args.html\",\n    \"description\": \"Discussing how to avoid subtle issues with string handling and when to use 'str' vs 'String'.\",\n    \"tags\": [\"strings\", \"arguments\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rust Patterns: Enums Instead Of Booleans\",\n    \"url\": \"https://blakesmith.me/2019/05/07/rust-patterns-enums-instead-of-booleans.html\",\n    \"description\": \"Discusses how using enums instead of booleans can express intent more clearly in Rust.\",\n    \"tags\": [\"enums\", \"booleans\", \"patterns\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Programming an ARM microcontroller in Rust at four different levels of abstraction\",\n    \"url\": \"https://pramode.in/2018/02/20/programming-a-microcontroller-in-rust-at-four-levels-of-abstraction/\",\n    \"description\": \"Demonstrates how Rust helps to move from low-level embedded code to high-level abstractions.\",\n    \"tags\": [\"microcontroller\", \"arm\", \"abstraction\"],\n    \"official\": false,\n    \"year\": 2018,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Iteration patterns for Result & Option\",\n    \"url\": \"http://xion.io/post/code/rust-iter-patterns.html\",\n    \"description\": \"Explores how to filter and partition iterators of Result and Option types idiomatically.\",\n    \"tags\": [\"iterators\", \"result\", \"option\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Lessons learned redesigning and refactoring a Rust Library\",\n    \"url\": \"https://web.archive.org/web/20220126172949/https://blog.mgattozzi.dev/refactor-rust/\",\n    \"description\": \"'RefCell', the builder pattern and more.\",\n    \"tags\": [\"refactoring\", \"design-patterns\", \"library\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Math with distances in Rust: safety and correctness across units\",\n    \"url\": \"https://www.ferrisellis.com/content/rust-implementing-units-for-types/\",\n    \"description\": \"How to create a system to cleanly and safely do arithmetic with lengths.\",\n    \"tags\": [\"math\", \"safety\", \"type-system\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"The balance between cost, useability and soundness in C bindings, and Rust-SDL2's release\",\n    \"url\": \"https://web.archive.org/web/20190509123207/https://cobrand.github.io/rust/sdl2/2017/05/07/the-balance-between-soundness-cost-useability.html\",\n    \"description\": \"Writing safe, sound, idiomatic libraries despite the limitations of the borrow checker.\",\n    \"tags\": [\"c-bindings\", \"sdl\", \"borrow-checker\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Russian Dolls and clean Rust code\",\n    \"url\": \"https://web.archive.org/web/20220126183049/https://blog.mgattozzi.dev/russian-dolls/\",\n    \"description\": \"How to use the full power of 'Option' and 'Result' (especially 'and_then()' and 'unwrap_or()').\",\n    \"tags\": [\"option\", \"result\", \"code-quality\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Elegant Library APIs in Rust\",\n    \"url\": \"https://deterministic.space/elegant-apis-in-rust.html\",\n    \"description\": \"Many helpful tips and tricks for writing libraries in Rust.\",\n    \"tags\": [\"libraries\", \"api-design\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Teaching libraries through good documentation\",\n    \"url\": \"https://deterministic.space/teaching-libraries.html\",\n    \"description\": \"How to use the full power of Rust's documentation support (e.g. doc tests).\",\n    \"tags\": [\"documentation\", \"libraries\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Pretty State Machine Patterns in Rust\",\n    \"url\": \"https://hoverbear.org/2016/10/12/rust-state-machine-pattern/\",\n    \"description\": \"How to represent a State Machine in an expressive and understandable way in Rust.\",\n    \"tags\": [\"state-machine\", \"patterns\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Ripgrep Code Review\",\n    \"url\": \"https://blog.mbrt.dev/posts/ripgrep/\",\n    \"description\": \"An analysis of the popular 'ripgrep' tool's source code.\",\n    \"tags\": [\"code-review\", \"ripgrep\", \"analysis\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rustic Bits\",\n    \"url\": \"https://llogiq.github.io/2016/02/11/rustic.html\",\n    \"description\": \"Small things that make for rustic code.\",\n    \"tags\": [\"best-practices\", \"code-quality\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Convenient and idiomatic conversions in Rust\",\n    \"url\": \"https://ricardomartins.cc/2016/08/03/convenient_and_idiomatic_conversions_in_rust\",\n    \"description\": \"Explains 'From<T>', 'Into<T>', 'TryFrom<T>', 'TryInto<T>', 'AsRef<T>' and 'AsMut<T>' with practical examples.\",\n    \"tags\": [\"conversions\", \"examples\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Idiomatic tree and graph like structures in Rust\",\n    \"url\": \"https://rust-leipzig.github.io/architecture/2016/12/20/idiomatic-trees-in-rust/\",\n    \"description\": \"Introduction to safe, dynamic, arena based tree structures without using lifetimes.\",\n    \"tags\": [\"tree-structures\", \"graphs\"],\n    \"official\": false,\n    \"year\": 2016,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rust traits for developer friendly libraries\",\n    \"url\": \"https://benashford.github.io/blog/2015/05/24/rust-traits-for-developer-friendly-libraries/\",\n    \"description\": \"Thoughts about implementing good Rust libraries.\",\n    \"tags\": [\"rust-traits\", \"libraries\", \"development\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Error Handling in Rust\",\n    \"url\": \"https://burntsushi.net/rust-error-handling/\",\n    \"description\": \"Understanding and handling errors in Rust in an idiomatic way.\",\n    \"tags\": [\"error-handling\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Creating a Rust function that accepts String or &str\",\n    \"url\": \"https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html/\",\n    \"description\": \"How to make calling your code both ergonomic and fast (zero-allocation).\",\n    \"tags\": [\"functions\", \"string-handling\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Creating a Rust function that returns a &str or String\",\n    \"url\": \"https://hermanradtke.com/2015/05/29/creating-a-rust-function-that-returns-string-or-str.html/\",\n    \"description\": \"How 'Into' and 'Cow' (Clone-on-write) work together to avoid allocations for string types.\",\n    \"tags\": [\"functions\", \"string-handling\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Effectively Using Iterators In Rust\",\n    \"url\": \"https://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html/\",\n    \"description\": \"Explanation of the 'Iter' and 'IntoIter' traits and how loops actually work in Rust.\",\n    \"tags\": [\"iterators\", \"traits\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Strategies for solving 'cannot move out of' borrowing errors in Rust\",\n    \"url\": \"https://hermanradtke.com/2015/06/09/strategies-for-solving-cannot-move-out-of-borrowing-errors-in-rust.html/\",\n    \"description\": \"Practical tips to help understand the borrow-checker and move semantics.\",\n    \"tags\": [\"borrow-checker\", \"move-semantics\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rayon: data parallelism in Rust\",\n    \"url\": \"https://smallcultfollowing.com/babysteps/blog/2015/12/18/rayon-data-parallelism-in-rust/\",\n    \"description\": \"Writing elegant parallel code in Rust.\",\n    \"tags\": [\"parallelism\", \"rayon\"],\n    \"official\": false,\n    \"year\": 2015,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Tricks of the Trait: Enabling Ergonomic Extractors\",\n    \"url\": \"https://www.youtube.com/watch?v=7DOYtnCXucw\",\n    \"description\": \"Rust Nation UK, Feb. 2023\",\n    \"tags\": [\"traits\", \"ergonomics\", \"extractors\"],\n    \"official\": false,\n    \"year\": 2023,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Nine Rules for Elegant Rust Library APIs\",\n    \"url\": \"https://www.youtube.com/watch?v=6-8-9ZV-2WQ\",\n    \"description\": \"Seattle Rust Meetup, Sep. 2022\",\n    \"tags\": [\"library-apis\", \"elegance\"],\n    \"official\": false,\n    \"year\": 2022,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Ergonomic APIs for hard problems\",\n    \"url\": \"https://www.youtube.com/watch?v=Phk0C-kLlho\",\n    \"description\": \"RustLab Conference, October 2022\",\n    \"tags\": [\"apis\", \"ergonomics\", \"rust-conference\"],\n    \"official\": false,\n    \"year\": 2022,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Macros for a More Productive Rust\",\n    \"url\": \"https://www.youtube.com/watch?v=dZiWkbnaQe8\",\n    \"description\": \"RustConf 2020\",\n    \"tags\": [\"macros\", \"productivity\", \"rustconf\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Making Rust Delightful\",\n    \"url\": \"https://www.youtube.com/watch?v=YSEx8wtlPWc\",\n    \"description\": \"RustCon Asia 2019\",\n    \"tags\": [\"conference\", \"development\"],\n    \"official\": false,\n    \"year\": 2019,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Idiomatic Rust - Writing Concise and Elegant Rust Code\",\n    \"url\": \"https://www.youtube.com/watch?v=P2mooqNMxMs\",\n    \"description\": \"FOSDEM 2018\",\n    \"tags\": [\"fosdem\"],\n    \"official\": false,\n    \"year\": 2018,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Idiomatic Rust Libraries\",\n    \"url\": \"https://www.youtube.com/watch?v=0zOg8_B71gE\",\n    \"description\": \"Rustfest Kiev\",\n    \"tags\": [\"rust-libraries\", \"rustfest\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Preferred way of passing `Path`-like types around?\",\n    \"url\": \"https://www.reddit.com/r/rust/comments/cekeq9/preferred_way_of_passing_pathlike_types_around/\",\n    \"description\": \"A Reddit discussion on the best practices for passing `Path`-like types in Rust.\",\n    \"tags\": [\"discussion\", \"path-types\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2020,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"forum\"\n  },\n  {\n    \"title\": \"Which is more idiomatic? Functional, imperative or a mix?\",\n    \"url\": \"https://users.rust-lang.org/t/which-is-more-idiomatic-functional-imperative-or-a-mix/11278\",\n    \"description\": \"A discussion on Rust's users forum about the idiomatic way to write Rust code: functional, imperative, or a mix of both.\",\n    \"tags\": [\"functional\", \"imperative\", \"coding-style\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"forum\"\n  },\n  {\n    \"title\": \"An idiomatic way to sum up values in a multidimensional Array\",\n    \"url\": \"https://users.rust-lang.org/t/an-idiomatic-way-to-sum-up-values-in-a-multidimensional-array/9485\",\n    \"description\": \"Forum discussion on idiomatic approaches to summing values in a multidimensional array in Rust.\",\n    \"tags\": [\"arrays\", \"summing\"],\n    \"official\": false,\n    \"year\": 2017,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"high\",\n    \"free\": true,\n    \"category\": \"forum\"\n  },\n  {\n    \"title\": \"The Four Horsemen of Bad Rust Code\",\n    \"url\": \"https://github.com/corrode/four-horsemen-talk\",\n    \"description\": \"A talk about common pitfalls in Rust code like overengineering and premature optimization.\",\n    \"tags\": [\"pitfalls\", \"common-mistakes\", \"patterns\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"talk\"\n  },\n  {\n    \"title\": \"Idiomatic Rust Workshop\",\n    \"url\": \"https://fettblog.eu/slides/idiomatic-rust/\",\n    \"description\": \"A talk/workshop about idiomatic Rust code focusing on effective use of existing syntax and design patterns\",\n    \"tags\": [\"tooling\", \"syntax\", \"design-patterns\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"workshop\"\n  },\n  {\n    \"title\": \"Rust Number Conversion: Don't Follow the Book...\",\n    \"url\": \"https://blog.notmet.net/2021/12/rust-number-conversion-dont-follow-the-book.../\",\n    \"description\": \"A blog post discussing the best practices for number conversion in Rust.\",\n    \"tags\": [\"number-conversion\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2021,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Practical guide to Error Handling in Rust\",\n    \"url\": \"https://dev-state.com/posts/error_handling/\",\n    \"description\": \"Hands-on guide with practical examples for common error handling scenarios in real-world applications.\",\n    \"tags\": [\"error-handling\", \"practical\", \"examples\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Three Kinds Of Unwrap\",\n    \"url\": \"https://zkrising.com/writing/three-unwraps/\",\n    \"description\": \"Understanding when and how to use different unwrap variants to prevent common panic-related bugs.\",\n    \"tags\": [\"error-handling\", \"unwrap\", \"panics\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Why choose async/await over threads?\",\n    \"url\": \"https://notgull.net/why-not-threads/\",\n    \"description\": \"Guidance on when to use async vs traditional threading to choose the right concurrency model.\",\n    \"tags\": [\"async\", \"threads\", \"concurrency\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Async Rust can be a pleasure to work with (without Send + Sync + 'static)\",\n    \"url\": \"https://emschwartz.me/async-rust-can-be-a-pleasure-to-work-with-without-send-sync-static/\",\n    \"description\": \"Relaxing trait bounds for simpler async code and ergonomic async patterns for single-threaded contexts.\",\n    \"tags\": [\"async\", \"ergonomics\", \"trait-bounds\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"When should I use String vs &str?\",\n    \"url\": \"https://steveklabnik.com/writing/when-should-i-use-string-vs-str/\",\n    \"description\": \"Guidance on choosing the right string type - a fundamental idiomatic Rust pattern.\",\n    \"tags\": [\"strings\", \"fundamentals\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Don't Worry About Lifetimes\",\n    \"url\": \"https://corrode.dev/blog/lifetimes/\",\n    \"description\": \"Demystifying lifetime annotations with practical lifetime management patterns.\",\n    \"tags\": [\"lifetimes\", \"fundamentals\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"How to Build Abstractions in Rust Applications\",\n    \"url\": \"https://orodu.net/2023/12/27/rust-abstractions.html\",\n    \"description\": \"Building effective abstractions in Rust based on software design principles.\",\n    \"tags\": [\n      \"abstractions\",\n      \"architecture\",\n      \"design\",\n      \"traits\",\n      \"dynamic-dispatch\"\n    ],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"The Ultimate Guide to Rust Newtypes\",\n    \"url\": \"https://www.howtocodeit.com/articles/ultimate-guide-rust-newtypes\",\n    \"description\": \"Using newtypes for type safety and compile-time domain validation.\",\n    \"tags\": [\"newtypes\", \"type-safety\", \"domain-modeling\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rust Iterators Beyond the Basics\",\n    \"url\": \"https://blog.jetbrains.com/rust/2024/03/12/rust-iterators-beyond-the-basics-part-i-building-blocks/\",\n    \"description\": \"Advanced iterator patterns for functional programming in Rust.\",\n    \"tags\": [\"iterators\", \"functional\", \"advanced\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Rust's Sneaky Deadlock With if let Blocks\",\n    \"url\": \"https://brooksblog.bearblog.dev/rusts-sneaky-deadlock-with-if-let-blocks/\",\n    \"description\": \"Subtle lock holding pattern that can cause critical deadlock pitfalls.\",\n    \"tags\": [\"deadlock\", \"if-let\", \"pitfalls\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"The Mediocre Programmer's Guide to Rust\",\n    \"url\": \"https://www.hezmatt.org/~mpalmer/blog/2024/05/01/the-mediocre-programmers-guide-to-rust.html\",\n    \"description\": \"Practical Rust without perfectionism - a pragmatic development approach.\",\n    \"tags\": [\"pragmatic\", \"practical\", \"philosophy\"],\n    \"official\": false,\n    \"year\": 2024,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Designing Error Types in Rust Libraries\",\n    \"url\": \"https://d34dl0ck.me/rust-bites-designing-error-types-in-rust-libraries/index.html\",\n    \"description\": \"Approaches to structuring error handling in library APIs for clarity and usability.\",\n    \"tags\": [\"error-handling\", \"api-design\", \"libraries\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"To panic or not to panic\",\n    \"url\": \"https://www.ncameron.org/blog/to-panic-or-not-to-panic/\",\n    \"description\": \"Error handling strategies and when panicking is appropriate versus returning Result types.\",\n    \"tags\": [\"error-handling\", \"panic\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Cancelling async Rust\",\n    \"url\": \"https://sunshowers.io/posts/cancelling-async-rust/\",\n    \"description\": \"Guide to cancellation safety in async Rust with patterns for resource management.\",\n    \"tags\": [\"async\", \"cancellation\", \"resource-management\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"advanced\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Prototyping in Rust\",\n    \"url\": \"https://corrode.dev/blog/prototyping/\",\n    \"description\": \"Rapid development methodology and idiomatic practices showing how to prototype effectively in Rust.\",\n    \"tags\": [\"prototyping\", \"development\", \"pragmatic\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Patterns for Defensive Programming in Rust\",\n    \"url\": \"https://corrode.dev/blog/defensive-programming/\",\n    \"description\": \"Defensive coding in Rust with best practices.\",\n    \"tags\": [\"defensive-programming\", \"best-practices\", \"patterns\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Flattening Rust's Learning Curve\",\n    \"url\": \"https://corrode.dev/blog/flattening-rusts-learning-curve/\",\n    \"description\": \"Best practices for learning Rust and reducing adoption friction.\",\n    \"tags\": [\"learning\", \"education\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"beginner\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Pitfalls of Safe Rust\",\n    \"url\": \"https://corrode.dev/blog/pitfalls-of-safe-rust/\",\n    \"description\": \"Essential guide to avoiding pitfalls even in safe Rust code.\",\n    \"tags\": [\"pitfalls\", \"safety\", \"best-practices\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Be Simple\",\n    \"url\": \"https://corrode.dev/blog/simple/\",\n    \"description\": \"Advocates for simpler, more maintainable code in Rust.\",\n    \"tags\": [\"simplicity\", \"philosophy\", \"maintainability\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"all\",\n    \"duration\": null,\n    \"interactivityLevel\": \"low\",\n    \"free\": true,\n    \"category\": \"article\"\n  },\n  {\n    \"title\": \"Level Up your Rust pattern matching\",\n    \"url\": \"https://blog.cuongle.dev/p/level-up-your-rust-pattern-matching\",\n    \"description\": \"Advanced pattern matching techniques and idiomatic usage.\",\n    \"tags\": [\"pattern-matching\", \"advanced\", \"idioms\"],\n    \"official\": false,\n    \"year\": 2025,\n    \"difficultyLevel\": \"intermediate\",\n    \"duration\": null,\n    \"interactivityLevel\": \"medium\",\n    \"free\": true,\n    \"category\": \"article\"\n  }\n]\n"
  }
]