Rust ==== .. _rust-license: License ------- Use the `MIT license `__. Development ----------- - Install Rust via `rustup `__ rather than via Homebrew. Preferences ----------- - Prefer crates in the top 250 according to `lib.rs `__ - Read the ``Cargo.toml`` files of OCP projects for inspiration - Use unstable language features or compiler flags instead of related crates. For example: - `let_chains `__ instead of `if_chain `__ - `once_cell `__ instead of `once_cell `__ (crate) or `lazy_static `__ - `on-broken-pipe `__ instead of `calm_io `__ .. seealso:: - `Serde documentation `__ .. Candidates for preferences https://github.com/open-contracting/cardinal-rs/issues/4 Performance ----------- .. seealso:: `coz `__ profiler Code style ---------- - `Avoid matching an Option or Result `__. Instead, use `Option `__ and `Result `__ methods. - `Don't panic `__. This includes ``panic!``, ``unreachable!``, ``unwrap()`` and ``expect()``. - Use the same word for macro tokens as for local variables, if appropriate. - Use ``super::*`` in ``mod tests`` only. Use ``crate::`` elsewhere. .. seealso:: - `Common Message Styles `__ Macros ~~~~~~ Prefer functions, but use macros if you need: - Variadic arguments, like ``println!`` or ``vec!``. - Code generation at the `item level `__, like creating structs. - Code generation at the `expression level `__, like accessing struct fields dynamically. .. seealso:: - `The Little Book of Rust Macros `__ - `Macros `__ in *The Rust Reference* Debugging: - `Debugging `__ in *The Little Book of Rust Macros* - `cargo-expand `__ - `proc-macro-error `__ Crates: - `paste `__, to use macro arguments to generate identifiers and strings. - To write procedural macros more easily: `quote `__, `proc_macro2 `__, `darling `__. Guard clauses ~~~~~~~~~~~~~ Code with too much indentation is hard to read. One option is to use guard clauses. For example: .. code-block:: rust let Some(inner_value) = outer_value else { return }; .. code-block:: rust let inner_value = match outer_value { Ok(o) => o, Err(e) => return e, }; Continuous integration ---------------------- Create a ``.github/workflows/ci.yml`` file. As a base, use: .. literalinclude:: samples/ci.yml :language: yaml Release process --------------- #. Ensure that you are on an up-to-date ``main`` branch: .. code-block:: bash git checkout main git pull --rebase #. Ensure that the package is ready for release: - All tests pass on continuous integration - The version number is correct in ``Cargo.toml`` - The changelog is up-to-date and dated #. Tag the release, replacing ``x.y.z`` twice: .. code-block:: bash git tag -a x.y.z -m 'x.y.z release.' #. Push the release: .. code-block:: bash git push --follow-tags #. Edit the GitHub release that is created by GitHub Actions, to add the ``description`` value from ``Cargo.toml`` followed by the relevant section of the changelog. #. If the software has a formula in our `Homebrew tap `__, update the ``url`` and ``sha256`` values. For example, from the ``homebrew-tap`` directory, after updating the ``url`` values, prepare the ``sha256`` values for the ``ocdscardinal`` formula with: .. code-block:: bash grep --only-matching -E 'https://.+zip' Formula/ocdscardinal.rb | xargs -I{} sh -c 'curl -sSL {} | shasum -a 256' Then, push the changes. #. Publish the crate: .. code-block:: bash cargo publish #. Announce on the `discussion group `__ if relevant Development ----------- Troubleshooting ~~~~~~~~~~~~~~~ If you're getting confusing compile errors, especially any involving type annotations, check that: - You wrote enough code. If you produce results that you don't use, the compiler still wants to determine their definite type. Adding more code to give the compiler a hint can spare adding optional type annotations. - Your annotations are correct. If you change your code but don't change your annotations, the compiler might report errors that are distantly related to the misannotation. - You duck type using trait objects: for example, ``Box`` to use ``std::io:stdin()`` and ``File::open(file).unwrap()`` interchangeably. The compiler can't determine which traits are relevant across the two types. If errors relate to ownership, try using: - ``Arc>``, as discussed in sections `16.3 `__ and `20.2 `__ of *The Rust Programming Language*. - ``Option`` with ``take()``, as discussed in sections `17.3 `__ and `20.3 `__ of *The Rust Programming Language*. To reduce the number of allocations, try using: - ``mem::take`` or ``mem::replace`` (`Rust Design Patterns `__). .. seealso:: - `Winning Fights against the Borrow Checker `__ .. _rust-learn: Learning ~~~~~~~~ Rust has no: - `Exception `__ - `Reflection `__ Introductions ^^^^^^^^^^^^^ - `The Rust Programming Language `__ (`Moving Captured Values Out of Closures and the Fn Traits `__) - `Exercism Rust Track `__: Read the most upvoted community solution after each exercise. - `Unofficial community Discord `__, in particular ``#rust-help`` and ``#rust-beginners`` .. tip:: Use `Rust Playground `__ to test code snippets. .. I prefer Exercism to Rustlings (https://github.com/rust-lang/rustlings). Rustlings' exercises often repeat examples from The Rust Programming Language, and are often solved by the compiler's feedback. I don't find it useful to read the examples in Rust by Example (https://doc.rust-lang.org/rust-by-example/), but I occasionally read it when it's a search result. Topics ^^^^^^ - `Command line apps in Rust `__ Memory container cheatsheet ^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. image:: https://media.githubusercontent.com/media/usagi/rust-memory-container-cs/master/3840x2160/rust-memory-container-cs-3840x2160-light-back-high-contrast.png :class: only-light .. image:: https://media.githubusercontent.com/media/usagi/rust-memory-container-cs/master/3840x2160/rust-memory-container-cs-3840x2160-dark-back-high-contrast.png :class: only-dark From `usagi/rust-memory-container-cs `__. Reference ^^^^^^^^^ - `The Rust Standard Library `__ - `The Rust Reference `__ - `docs.rs `__ for crate documentation .. tip:: Scroll up after the page loads to access the within-crate search bar.