Rust Coding Guidelines (Chinese Edition)

repository·main·Indexed 21 days ago

https://github.com/rust-coding-guidelines/rust-coding-guidelines-zh

A community-driven Chinese translation of the Rust Coding Guidelines (V 1.0 beta). It provides a unified standard for Rust development, covering coding style, best practices, and specific implementation patterns such as the Builder pattern, efficient iterator usage, and error handling strategies for applications versus libraries. The documentation also includes cheat sheets for floating-point numbers and guidance on development environments, toolchains, and Cargo.

Tokens
152.3K
Snippets
453
Records
606
Agent score
74%

What's inside rust-coding-guidelines-zh

  1. Overview of Rust Toolchain Detection Tools

    main

    The Rust ecosystem provides several essential tools for maintaining code quality and consistency. Key tools mentioned include:

    • Cargo fmt: Used for automatic code formatting to ensure a consistent style across the codebase.
    • Cargo Clippy: A powerful linting tool that catches common mistakes and suggests idiomatic improvements to your Rust code.
  2. Overview of Rust Coding Guidelines (Chinese Edition)

    main
    This repository provides a Chinese translation of the Rust Coding Guidelines. It aims to serve as a unified standard for Rust development, intended to be maintained collaboratively by various companies and organizations. Developers and companies can adopt these guidelines and adapt them to their specific business domains and team habits, contributing improvements back to the project.
  3. Overview of Lock-free Concurrency in Rust

    main
    Rust supports atomic types with a memory ordering model identical to C++20. While lock-free programming can improve performance in specific high-contention scenarios, it is complex and error-prone. The guidelines recommend prioritizing synchronous locks unless lock-free approaches are strictly necessary for performance or architectural requirements.
  4. Overview of Rust collection types

    main

    Rust collections are categorized into four main types based on their data structure and access patterns:

    • Linear Sequences: Used for ordered data. Includes Vec, VecDeque, and LinkedList.
    • Maps (Key-Value): Used for associating keys with values. Includes HashMap and BTreeMap.
    • Sets: Used for storing unique elements. Includes HashSet and BTreeSet.
    • Other: Specialized structures like BinaryHeap (a priority queue).
  5. Understand the purpose and scope of the Rust Coding Guidelines

    main

    The Rust Coding Guidelines (currently in V 1.0 beta) aim to provide a comprehensive, unified standard covering both coding style and specific coding practices. While many open-source projects maintain their own style guides to unify contributors, this project serves as a general reference that companies and communities can adapt to their specific business domains and team habits.

    Key components of the overview include:

    • Why the guidelines are needed: Explains the motivation behind a unified standard.
    • Basic conventions: Outlines the fundamental agreements used throughout the guidelines.
  6. Guidelines for using Rust standard library built-in traits

    main

    The Rust standard library provides numerous built-in traits. To ensure code correctness, performance, and idiomatic design, follow the specific guidelines provided for each trait implementation or usage. These guidelines cover common pitfalls in implementing traits like Borrow, Default, Copy, Clone, From, Into, Hash, Ord, and Deref.

    Available guidelines include:
    
    - **Borrow**: Ensure consistency when implementing `Borrow`.
    - **Default**: Use specific type `default()` instead of `Default::default()`; prefer `#[derive(Default)]` over manual implementation.
    - **Copy/Clone**: Do not implement `Copy` for iterators; do not call `std::mem::drop` or `std::mem::forgot` on `Copy` or reference types; use `.copied()` instead of `.cloned()` for `Copy` types; avoid manual `Clone` for `Copy` types.
    - **Hash/Ord**: Avoid manual `PartialEq` when using `#[derive(Hash)]`; avoid manual `PartialOrd` when using `#[derive(Ord)]`.
    - **From/Into**: Implement `From` instead of `Into`.
    - **Deref**: Do not use `Deref` to simulate inheritance.
  7. The purpose and benefits of Rust coding standards

    main

    A formal coding standard complements automated tools by providing a systematic framework for writing idiomatic Rust. The primary goals are:

    1. Code Quality: Improve readability, maintainability, robustness, and portability by leveraging Rust's language features.
    2. Unsafe Safety: Provide specific guidelines for writing safe and standardized Unsafe Rust code.
    3. Efficiency: Create systematic, easy-to-apply, and easy-to-check rules that help developers avoid common pitfalls.
    4. Proactive Development: Provide a global mental model so developers can write high-quality code from the start, rather than relying on a reactive "fix warnings" workflow after running rustfmt or clippy.
    5. Knowledge Gap Bridging: Act as a reference for areas where knowledge gaps might lead to program errors, serving as more than just a tutorial.
  8. Ensure I/O safety when using raw file descriptors

    main

    When designing APIs that perform I/O operations using raw handles (such as file descriptors), be aware that using the AsRawFd trait can be unsafe. Because AsRawFd::as_raw_fd returns a raw integer (RawFd) without restrictions, an end-user can pass any arbitrary integer to your function. This can lead to:

    1. Accessing incorrect resources: Users can pass valid but unintended file descriptors (e.g., do_some_io(&7)).
    2. Breaking encapsulation: Users can create aliases for private handles, leading to "Action at a distance" (where behavior in one part of the program is unexpectedly affected by distant, hard-to-trace code).
    3. Memory safety violations: In certain edge cases, violating I/O safety can directly lead to memory safety issues.

    To prevent this, avoid accepting AsRawFd if you need to guarantee that the I/O is performed only on a specific, controlled resource. Instead, consider accepting types that own the resource or use higher-level abstractions that enforce ownership and lifetime rules.

    // Example of an unsafe API pattern that allows arbitrary I/O
    pub fn do_some_io<FD: AsRawFd>(input: &FD) -> io::Result<()> {
        some_syscall(input.as_raw_fd())
    }
    
    // This allows dangerous calls like:
    // do_some_io(&7) 
  9. Distinguish between regular comments and documentation comments in Rust

    main

    In Rust, comments are categorized into two types: regular comments and documentation comments. When following these guidelines, note that the term "comments" refers to both types, while the term "documentation" specifically refers to documentation comments.

    Regular Comments

    Used for internal notes that are not intended to be part of the public API documentation. Use:

    • // (Line comment)
    • /* ... */ (Block comment)

    Documentation Comments

    Used to generate documentation via rustdoc. These are visible to users of your API.

    • /// (Outer documentation comment: used to document the item following the comment, such as a function or struct).
    • //! (Inner documentation comment: used to document the item containing the comment, such as a module or a crate).
    • /** ... **/ (Block documentation comment).
    // This is a regular line comment
    /* This is a regular block comment */
    
    /// This is an outer documentation comment for the following function
    fn my_function() {}
    
    //! This is an inner documentation comment for the current module
  10. Identify and use common Rust smart pointers

    main

    In Rust, smart pointers are types that participate in automatic heap management, reference counting, or abstract pointer semantics. A type is generally considered a smart pointer if it implements the Deref trait or the Drop trait.

    Common categories of smart pointers include:

    • Heap Memory Management: Box<T> is used to allocate data on the heap.
    • Reference Counting: Rc<T> (single-threaded) and Arc<T> (atomic/multi-threaded) manage shared ownership via reference counting.
    • Interior Mutability Containers: Cell<T> and RefCell<T> allow mutating data even when there are immutable references to the container.
  11. Avoid using the `Deref` trait to simulate inheritance

    main

    The Deref trait is specifically intended for implementing custom pointer types (e.g., smart pointers like Box or String). While implementing Deref can create behavior similar to inheritance (allowing a wrapper type to access methods of an inner type), this is strongly discouraged in Rust.

    Rust emphasizes explicit conversions. Deref is one of the few sources of implicit behavior in the language. Overusing it increases the amount of implicit coercion in your codebase, which can lead to subtle bugs and make code harder to reason about.

    // BAD PRACTICE: Using Deref to simulate inheritance
    use std::ops::Deref;
    
    struct Foo {}
    
    impl Foo {
        fn m(&self) {
            // ...
        }
    }
    
    struct Bar {
        f: Foo
    }
    
    impl Deref for Bar {
        type Target = Foo;
    
        fn deref(&self) -> &Foo {
            &self.f
        }
    }
    
    fn main() {
        let bar = Bar { f: Foo {} };
        // This call is implicit via Deref coercion, which is discouraged for inheritance simulation
        bar.m();
    }