1.
Overview
❱
1.1.
Why you need the Rust coding specification
1.2.
Basic conventions of the coding specification
2.
Coding Style
❱
2.1.
Naming
❱
2.1.1.
P.NAM.01 The naming convention for identifiers in the same crate should use a uniform word order
2.1.2.
P.NAM.02 Names for cargo features should not contain meaningless placeholders
2.1.3.
P.NAM.03 Identifier naming should be in line with reading habits
2.1.4.
P.NAM.04 The larger the scope, the more precise the naming, and the opposite should be short
2.1.5.
P.NAM.05 The getter family of methods used to access or retrieve data should not normally have the prefix get_
2.1.6.
P.NAM.06 Follow the iter/ iter_mut/ into_iter specification to generate iterators
2.1.7.
P.NAM.07 Avoid using special names such as language built-in reserved words, keywords, built-in types and traits
2.1.8.
P.NAM.08 Avoid adding type identifiers to the naming of variables
2.1.9.
P.NAM.09 Global static variables should be defined with the prefix G_ to distinguish them from constants
2.1.10.
G.NAM.01 Use a uniform naming style
2.1.11.
G.NAM.02 Type conversion function naming needs to follow ownership semantics
2.2.
Format
❱
2.2.1.
P.FMT.01 Automatic code formatting with rustfmt
2.2.2.
P.FMT.02 Use spaces instead of tabs for indentation
2.2.3.
P.FMT.03 The maximum width of line spacing is one blank line
2.2.4.
P.FMT.04 Language items should be defined with the left braces position on the same line
2.2.5.
P.FMT.05 Block indentation should be maintained when multiple identifiers are present
2.2.6.
P.FMT.06 When there is a multi-line expression operation, the operator should be placed at the beginning of the line
2.2.7.
P.FMT.07 Both enumeration variants and structure fields should be left aligned
2.2.8.
P.FMT.08 Line feeds for functions with more than five parameters or imported modules with more than four parameters
2.2.9.
P.FMT.09 Use different spaces style for different scenarios
2.2.10.
P.FMT.10 match arms should have good readability
2.2.11.
P.FMT.11 Imported modules should be grouped with good readability
2.2.12.
P.FMT.12 Declarative macros arms should be well readable
2.2.13.
P.FMT.13 Do not omit field names when initializing named structure fields
2.2.14.
P.FMT.14 extern external functions need to be explicitly specified C-ABI
2.2.15.
P.FMT.15 Deconstructing a tuple allows the use of .. to refer to the remaining elements
2.2.16.
P.FMT.16 Do not merge multiple unrelated traits in derived macros into the same line
2.3.
Code Comments
❱
2.3.1.
P.CMT.01 The code can be self-commenting and the documentation should be concise.
2.3.2.
P.CMT.02 Comments should have a width limit
2.3.3.
P.CMT.03 Use line comments and avoid block comments
2.3.4.
P.CMT.04 File header comments include a copyright notice
2.3.5.
P.CMT.05 Use FIXME and TODO in comments to help with team collaboration
2.3.6.
G.CMT.01 Error comments need to be added to the documentation of functions that return Result types in the public
2.3.7.
G.CMT.02 If a Panic occurs under certain circumstances in the public API, add a Panic comment to the corresponding document
2.3.8.
G.CMT.03 Use spaces in document comments instead of tabs
3.
Coding Practice
❱
3.1.
Const
❱
3.1.1.
G.CNS.01 Use predefined consts for float approximation in scientific computation
3.1.2.
G.CNS.02 Shouldn't assert const bool type
3.1.3.
G.CNS.03 Shouldn't declare interior mutable container as consts
3.1.4.
G.CNS.04 Shouldn't add explicit 'static lifetime in constant declaration
3.1.5.
G.CNS.05 Should use const fn as much as possible
3.2.
Static Const
❱
3.2.1.
G.STV.01 Shouldn't use static mut as global variable directly
3.3.
Local Const
❱
3.3.1.
P.VAR.01 一般情况下避免先声明可变变量再赋值
3.3.2.
P.VAR.02 利用变量遮蔽功能保证变量安全使用
3.3.3.
G.VAR.01 以解构元组方式定义超过四个变量时不应使用太多无意义变量名
3.3.4.
G.VAR.02 不应使用非 ASCII 字符作为标识符
3.3.5.
G.VAR.03 变量遮蔽功能应当合理使用
3.3.6.
G.VAR.04 避免因局部变量过大而导致的大量栈分配
3.4.
Data Type
❱
3.4.1.
P.TYP.01 必要时,应使类型可以表达更明确的语义,而不是只是直接使用原生类型
3.4.2.
G.TYP.01 类型转换尽可能使用安全的转换函数代替 as
3.4.3.
G.TYP.02 数字字面量在使用的时候应该明确标注类型
3.4.4.
G.TYP.03 不要用数字类型边界值判断能否安全转换,而应使用 try_from 方法
3.4.5.
Bool
❱
3.4.5.1.
G.TYP.BOL.01 不应将布尔值和布尔字面量进行比较
3.4.5.2.
G.TYP.BOL.02 如果 match 匹配表达式为布尔类型,宜使用 if 表达式来代替
3.4.5.3.
G.TYP.BOL.03 不应将数字类型转换为布尔值
3.4.5.4.
G.TYP.BOL.04 禁止在if表达式条件中使用块结构
3.4.5.5.
G.TYP.BOL.05 非必要时,布尔运算应使用逻辑运算符( &&/||)而非位运算符 (&/|)
3.4.5.6.
G.TYP.BOL.06 不应使用数字代替布尔值
3.4.6.
Character
❱
3.4.6.1.
G.TYP.CHR.01 不应将字符字面量强制转换为 u8
3.4.6.2.
G.TYP.CHR.02 字符串方法中如果需要单个字符的值作为参数,宜使用字符而非字符串
3.4.6.3.
G.TYP.CHR.03 需要将整数转换为字符时,应使用安全转换函数,而非 transmute
3.4.7.
Integer
❱
3.4.7.1.
G.TYP.INT.01 在用整数计算的时候需要考虑整数溢出、回绕和截断的风险
3.4.7.2.
G.TYP.INT.02 避免在有符号整数和无符号整数之间进行强制转换
3.4.7.3.
G.TYP.INT.03 对负数取模计算的时候不应使用 %
3.4.8.
Float
❱
3.4.8.1.
G.TYP.FLT.01 使用浮点数字面量时,要警惕是否存在被Rust编译器截断的风险
3.4.8.2.
G.TYP.FLT.02 从任何数字类型转换为浮点类型时注意避免损失精度
3.4.8.3.
G.TYP.FLT.03 对精度高要求的场景下,使用浮点数进行运算和比较时需要注意精度损失
3.4.8.4.
G.TYP.FLT.04 宜使用Rust内置方法处理浮点数计算
3.4.8.5.
G.TYP.FLT.05 禁止在浮点数和整数相互转换时使用 transmute
3.4.9.
Slice
❱
3.4.9.1.
P.TYP.SLC.01 宜使用切片迭代器来代替手工索引
3.4.9.2.
P.TYP.SLC.02 宜使用切片模式来提升代码的可读性
3.4.10.
Tuple
❱
3.4.10.1.
G.TYP.TUP.01 使用元组时,其元素不宜超过3个
3.4.11.
Array
❱
3.4.11.1.
G.TYP.ARR.01 创建大全局数组时宜使用静态变量而非常量
3.4.11.2.
G.TYP.ARR.02 使用数组索引时禁止越界访问
3.4.11.3.
G.TYP.ARR.03 当数组元素为原生数据类型(Primitive),排序时优先选用非稳定排序
3.4.12.
Vector
❱
3.4.12.1.
P.TYP.VEC.01 非必要时不宜使用动态数组
3.4.12.2.
P.TYP.VEC.02 创建动态数组时,宜预先分配足够容量,避免后续操作中产生多次分配
3.4.12.3.
G.TYP.VEC.01 禁止访问未初始化的数组
3.4.13.
Struct
❱
3.4.13.1.
P.TYP.SCT.01 为结构体实现构造性方法时,避免构造后再初始化的情况
3.4.13.2.
P.TYP.SCT.02 结构体实例需要默认实现时,宜使用Default特质
3.4.13.3.
G.TYP.SCT.01 对外导出的公开的 Struct,宜添加#[non_exhaustive]属性
3.4.13.4.
G.TYP.SCT.02 当结构体中有超过三个布尔类型的字段,宜将其独立为新的枚举类
3.4.13.5.
G.TYP.SCT.03 宜使用结构体功能更新语法来提升代码可读性
3.4.14.
Enumeration
❱
3.4.14.1.
G.TYP.ENM.01 合理使用map和and_then方法
3.4.14.2.
G.TYP.ENM.02 不应自行创建空枚举
3.4.14.3.
G.TYP.ENM.03 在使用类似 C 语言的枚举写法且使用repr(isize/usize) 布局时注意 32位架构上截断的问题
3.4.14.4.
G.TYP.ENM.04 不宜在use语句中引入Enum的全部变体(variants)
3.4.14.5.
G.TYP.ENM.05 对外导出的公开Enum,宜添加#[non_exhaustive]属性
3.4.14.6.
G.TYP.ENM.06 Enum内变体的大小差异不宜过大
3.5.
Express
❱
3.5.1.
G.EXP.01 当需要对表达式求值后重新赋值时,宜使用复合赋值模式
3.5.2.
G.EXP.02 不宜在比较中使用不兼容的位掩码
3.5.3.
G.EXP.03 不应利用数组表达式的边界检查来 Panic,而应使用断言
3.5.4.
G.EXP.04 自增或自减运算使用+=或-=
3.5.5.
G.EXP.05 使用括号来清楚表示表达式的计算顺序
3.5.6.
G.EXP.06 避免在比较中添加无用的掩码操作
3.6.
Control Flow
❱
3.6.1.
P.CTF.01 避免滥用迭代器
3.6.2.
P.CTF.02 优先使用模式匹配而非判断后再取值
3.6.3.
G.CTF.01 当需要通过多个if判断来比较大小来区分不同情况时,优先使用match和cmp来代替if表达式
3.6.4.
G.CTF.02 if条件表达式分支中如果包含了else if分支也应该包含else分支
3.6.5.
G.CTF.03 如果要通过 if 条件表达式来判断是否 Panic,请优先使用断言
3.6.6.
G.CTF.04 在 Match 分支的 Guard 语句中不要使用带有副作用的条件表达式
3.7.
String
❱
3.7.1.
P.STR.01 处理字符串元素时优先按字节处理而非字符
3.7.2.
P.STR.02 创建字符串时,宜预先分配大约足够的容量来避免后续操作中产生多次分配
3.7.3.
P.STR.03 在使用内建字符串处理函数或方法的时候,应注意避免隐藏的嵌套迭代或多次迭代
3.7.4.
P.STR.04 只在合适的场景下,使用正则表达式第三方库regex
3.7.5.
P.STR.05 在拼接字符串时,优先使用format!
3.7.6.
G.STR.01 在实现Display特质时不应调用to_string()方法
3.7.7.
G.STR.02 在追加字符串时使用push_str方法
3.7.8.
G.STR.03 将只包含 ASCII字符的字符串字面量转为字节序列可以直接使用b"str" 语法代替调用as_bytes方法
3.7.9.
G.STR.04 需要辨别字符串的字符开头或结尾字符时,不应按字符迭代比较
3.7.10.
G.STR.05 对字符串按指定位置进行切片的时候需要小心破坏其 UTF-8 编码
3.8.
Collections
❱
3.8.1.
P.CLT.01 创建HashMap、VecDeque时,可以预先分配大约足够的容量来避免后续操作中产生多次分配
3.8.2.
G.CLT.01 非必要情况下,不要使用LinkedList,而用Vec或VecDeque代替
3.9.
Function Design
❱
3.9.1.
P.FUD.01 Should rebind variables which pass into closure
3.9.2.
P.FUD.02 Don't Use return for return value
3.9.3.
G.FUD.01 Less than 5 function parameters
3.9.4.
G.FUD.02 Should input as reference if parameter derives Copy and its value inputed by-value is a big number
3.9.5.
G.FUD.03 Should refactor into customized struct or enum if there are too many bool type's function parameters
3.9.6.
G.FUD.04 Should input by-value but by-ref if parameter derived Copy, and its value is a small enough number
3.9.7.
G.FUD.05 Don't always specify #[inline(always)] for function
3.9.8.
G.FUD.06 Parameters Should be compatible with multiple types
3.10.
Generic
❱
3.10.1.
P.GEN.01 用泛型来抽象公共语义
3.10.2.
P.GEN.02 不要随便使用 impl Trait 语法替代泛型限定
3.10.3.
P.GEN.03 不要使用太多泛型参数和 trait 限定,否则会增长编译时间
3.10.4.
P.GEN.04 为泛型类型实现方法时,impl 中声明的泛型类型参数一定要被用到
3.10.5.
P.GEN.05 定义泛型函数时,如果该函数实现用到来自 trait 定义的相关行为,需要为泛型指定相关 trait 的限定
3.10.6.
G.GEN.01 不要在泛型位置上使用内建类型
3.10.7.
G.GEN.02 使用 Rust 标准库中某些方法,要注意避免使用其泛型默认实现,而应该使用具体类型的实现
3.11.
Trait
❱
3.11.1.
P.TRA.01 使用 trait 时要注意 trait 一致性规则
3.11.2.
标准库内置 trait
❱
3.11.2.1.
P.TRA.BLN.01 在实现Borrow特质时,需要注意一致性
3.11.2.2.
G.TRA.BLN.01 应该具体类型的 default() 方法代替 Default::default() 调用
3.11.2.3.
G.TRA.BLN.02 不要为迭代器实现Copy 特质
3.11.2.4.
G.TRA.BLN.03 能使用派生宏(Derive)自动实现Default特质就不要用手工实现
3.11.2.5.
G.TRA.BLN.04 在使用#[derive(Hash)] 的时候,避免再手工实现 PartialEq
3.11.2.6.
G.TRA.BLN.05 在使用#[derive(Ord)] 的时候,避免再手工实现 PartialOrd
3.11.2.7.
G.TRA.BLN.06 不要对实现 Copy 或引用类型调用 std::mem::drop 和 std::mem::forgot
3.11.2.8.
G.TRA.BLN.07 对实现 Copy 的可迭代类型来说,要通过迭代器拷贝其所有元素时,应该使用 copied方法,而非cloned
3.11.2.9.
G.TRA.BLN.08 实现 From 而不是 Into
3.11.2.10.
G.TRA.BLN.09 一般情况下不要给 Copy 类型手工实现 Clone
3.11.2.11.
G.TRA.BLN.10 不要随便使用Deref特质来模拟继承
3.11.3.
trait 对象
❱
3.11.3.1.
P.TRA.OBJ.01 根据场景合理选择使用trait对象或泛型静态分发
3.11.3.2.
P.TRA.OBJ.02 除非必要,避免自定义虚表
3.12.
Error Handling
❱
3.12.1.
P.ERR.01 当传入函数的参数值因为超出某种限制可能会导致函数调用失败,应该使用断言
3.12.2.
P.ERR.02 在确定 Option 和 Result<T, E>类型的值不可能是 None 或 Err 时,请用 expect 代替 unwrap()
3.12.3.
G.ERR.01 在处理 Option 和 Result<T, E> 类型时,不要随便使用 unwrap
3.12.4.
G.ERR.02 不要滥用 expect,请考虑用 unwrap_or_ 系列方法代替
3.13.
Memory Management
❱
3.13.1.
生命周期
❱
3.13.1.1.
P.MEM.LFT.01 生命周期参数命名尽量有意义且简洁
3.13.1.2.
P.MEM.LFT.02 通常需要显式地标注生命周期,而非利用编译器推断
3.13.2.
智能指针
❱
3.13.2.1.
P.MEM.SPT.01 使用 RefCell<T> 时宜使用 try_borrow/try_borrow_mut 方法
3.13.3.
Box 类型
❱
3.13.3.1.
G.MEM.BOX.01 一般情况下,不应直接对 Box<T> 进行借用
3.13.3.2.
G.MEM.BOX.02 一般情况下,不应直接对已经在堆上分配内存的类型进行 Box 装箱
3.13.3.3.
G.MEM.BOX.03 一般情况下,不应直接对栈分配类型进行 Box 装箱
3.13.4.
Drop 析构
❱
3.13.4.1.
G.MEM.DRP.01 要注意防范内存泄漏
3.14.
Module
❱
3.14.1.
P.MOD.01 合理控制对外接口和模块之间的可见性
3.14.2.
P.MOD.02 将模块的测试移动到单独的文件,有助于增加编译速度
3.14.3.
G.MOD.01 使用导入模块中的类型或函数,在某些情况下需要带模块名前缀
3.14.4.
G.MOD.02 如果是作为库供别人使用,在 lib.rs中重新导出对外类型、函数和 trait 等
3.14.5.
G.MOD.03 导入模块不要随便使用 通配符*
3.14.6.
G.MOD.04 一个项目中应该避免使用不同的模块布局风格
3.14.7.
G.MOD.05 不要在私有模块中设置其内部类型或函数方法为 pub(crate)
3.15.
Package Management
❱
3.15.1.
P.CAR.01 应该尽量把项目划分为合理的 crate 组合
3.15.2.
P.CAR.02 不要滥用 Features
3.15.3.
P.CAR.03 使用 cargo features 来代替 --cfg 条件编译参数
3.15.4.
P.CAR.04 如果可能的话,使用 cfg! 来代替 #[cfg]
3.15.5.
G.CAR.01 当项目是可执行程序而非库时,建议使用 src/main.rs 和 src/lib.rs 模式
3.15.6.
G.CAR.02 Crate 的 Cargo.toml 中应该包含必要的元信息
3.15.7.
G.CAR.03 Feature 命名应该避免否定式或多余的前后缀
3.15.8.
G.CAR.04 Cargo.toml 中依赖包版本不应使用通配符
3.16.
Macro
❱
3.16.1.
P.MAC.01 不要轻易使用宏
3.16.2.
P.MAC.02 实现宏语法的时候,应该尽量贴近 Rust 语法
3.16.3.
G.MAC.01 dbg!() 宏只应该用于调试代码
3.16.4.
G.MAC.02 使用宏时应该考虑宏展开会让编译文件膨胀的影响
3.16.5.
Declarative Macro
❱
3.16.5.1.
P.MAC.DCL.01 不要将声明宏内的变量作为外部变量使用
3.16.5.2.
P.MAC.DCL.02 在编写多个宏规则时,应该先从匹配粒度最小的开始写
3.16.5.3.
P.MAC.DCL.03 不要在片段分类符跟随它不匹配的符号
3.16.5.4.
P.MAC.DCL.04 匹配规则要精准,不要模糊不清
3.16.5.5.
P.MAC.DCL.05 使用宏替换(substitution)元变量的时候要注意选择合适的片段分类符
3.16.5.6.
P.MAC.DCL.06 当宏需要接收 self 时需要注意
3.16.5.7.
P.MAC.DCL.07 确保在宏定义之后再去调用宏
3.16.5.8.
P.MAC.DCL.08 同一个 crate 内定义的宏相互调用时,需要注意卫生性
3.16.6.
Procedural Macro
❱
3.16.6.1.
P.MAC.PRO.01 不要使用过程宏来规避静态分析检查
3.16.6.2.
P.MAC.PRO.02 实现过程宏时要对关键特性增加测试
3.16.6.3.
P.MAC.PRO.03 保证过程宏的卫生性
3.16.6.4.
P.MAC.PRO.04 给出正确的错误位置
3.16.6.5.
P.MAC.PRO.05 代码生成要按情况选择使用过程宏还是 build.rs
3.16.6.6.
P.MAC.PRO.06 build.rs 生成的代码要保证没有任何警告
3.17.
Multi Threads
❱
3.17.1.
Lock
❱
3.17.1.1.
P.MTH.LCK.01 多线程下要注意识别锁争用的情况,避免死锁
3.17.1.2.
G.MTH.LCK.01 对布尔或引用并发访问应该使用原子类型而非互斥锁
3.17.1.3.
G.MTH.LCK.02 宜使用 Arc / Arc<[T]> 来代替 Arc / Arc<Vec>
3.17.1.4.
G.MTH.LCK.03 尽量避免直接使用标准库 std::sync 模块中的同步原语,替换为 parking_lot
3.17.1.5.
G.MTH.LCK.04 尽量避免直接使用标准库 std::sync::mpsc 模块中的 channel,替换为 crossbeam
3.17.2.
Lock Free
❱
3.17.2.1.
P.MTH.LKF.01 除非必要,否则建议使用同步锁
3.17.2.2.
P.MTH.LKF.02 使用无锁编程时,需要合理选择内存顺序
3.18.
Async
❱
3.18.1.
P.ASY.01 异步编程并不适合所有场景,计算密集型场景应该考虑同步编程
3.18.2.
G.ASY.01 在 async 块或函数中调用 async 函数或闭包请不要忘记添加.await
3.18.3.
G.ASY.02 在跨 await 调用中,需要对其持有的同步互斥锁进行处理
3.18.4.
G.ASY.03 在跨 await 调用中,需要对其持有 RefCell 的引用进行处理
3.18.5.
G.ASY.04 避免定义不必要的异步函数
3.18.6.
G.ASY.05 避免在异步处理过程中包含阻塞操作
3.19.
Unsafe Rust
❱
3.19.1.
P.UNS.01 不要为了逃避编译器安全检查而滥用 Unsafe Rust
3.19.2.
P.UNS.02 不要为了提升性能而盲目使用 Unsafe Rust
3.19.3.
G.UNS.01 不宜为带有 unsafe 命名的类型或方法创建别名
3.19.4.
Safety Abstract
❱
3.19.4.1.
P.UNS.SAS.01 代码中要注意是否会因为 Panic 发生而导致内存安全问题
3.19.4.2.
P.UNS.SAS.02 Unsafe 代码编写者有义务检查代码是否满足安全不变式
3.19.4.3.
P.UNS.SAS.03 不要随便在公开的 API 中暴露未初始化内存
3.19.4.4.
P.UNS.SAS.04 避免因为 Panic Safety 而导致双重释放
3.19.4.5.
P.UNS.SAS.05 手动实现 auto trait 时要充分考虑其安全性
3.19.4.6.
P.UNS.SAS.06 不要随便在公开的 API 中暴露裸指针
3.19.4.7.
P.UNS.SAS.07 在抽象安全方法的同时,也建议为性能考虑而增加相应的 Unsafe 方法
3.19.4.8.
P.UNS.SAS.08 函数参数是不可变借用的时候,返回值不应该是可变借用
3.19.4.9.
P.UNS.SAS.09 在任何 Unsafe 块之前都应该加 SAFETY 注释
3.19.4.10.
G.UNS.SAS.01 在公开的 unsafe 函数的文档中必须增加 Safety 注释
3.19.4.11.
G.UNS.SAS.02 在 Unafe 函数中应使用 assert! 而非 debug_assert! 去校验边界条件
3.19.5.
Modification of Raw Pointer
❱
3.19.5.1.
P.UNS.PTR.01 不要将裸指针在多线程间共享
3.19.5.2.
P.UNS.PTR.02 建议使用 NonNull<T> 来替代 *mut T
3.19.5.3.
P.UNS.PTR.03 使用指针类型构造泛型结构体时,需要使用 PhantomData<T> 来指定 T上的协变和所有权
3.19.5.4.
G.UNS.PTR.01 当指针类型被强转为和当前内存对齐不一致的指针类型时,禁止对其解引用
3.19.5.5.
G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针
3.19.5.6.
G.UNS.PTR.03 尽量使用 pointer::cast 来代替 使用 as 强转指针
3.19.6.
Union
❱
3.19.6.1.
P.UNS.UNI.01 除了与 C 交互,尽量不要使用 Union
3.19.6.2.
P.UNS.UNI.02 不要把联合体的不同变体用在不同生命周期内
3.19.7.
Memory
❱
3.19.7.1.
P.UNS.MEM.01 要注意选择合适的结构体、元组、枚举的数据布局
3.19.7.2.
P.UNS.MEM.02 不能修改其它进程或动态库的内存变量
3.19.7.3.
P.UNS.MEM.03 不能让 String/Vec 自动 Drop 其它进程或动态库的内存数据
3.19.7.4.
P.UNS.MEM.04 尽量用可重入(reentrant)版本的 C-API 或系统调用
3.19.7.5.
P.UNS.MEM.05 如果需要使用位域,推荐使用第三方库
3.19.7.6.
G.UNS.MEM.01 使用 MaybeUninit<T> 来处理未初始化的内存
3.19.8.
FFi
❱
3.19.8.1.
P.UNS.FFI.01 避免从公开的 Rust API 直接传字符串到 C 中
3.19.8.2.
P.UNS.FFI.02 在使用标准库 std::ffi 模块提供的类型时需要仔细查看其文档
3.19.8.3.
P.UNS.FFI.03 当使用来自 C 的指针时,如果该指针需要管理内存,则需要为包装该指针的 Rust 类型实现 Drop 特质
3.19.8.4.
P.UNS.FFI.04 如果一个函数正在跨越 FFi 边界,那么需要处理 Panic
3.19.8.5.
P.UNS.FFI.05 建议使用诸如标准库或 libc crate 所提供的可移植类型别名,而不是特定平台的类型
3.19.8.6.
P.UNS.FFI.06 Rust 和 C 之间传递字符或字符串时需要注意字符串要符合 C-ABI 以及 字符串的编码
3.19.8.7.
P.UNS.FFI.07 不要为任何传出外部的类型实现 Drop
3.19.8.8.
P.UNS.FFI.08 FFi 中要进行合理的错误处理
3.19.8.9.
P.UNS.FFI.09 当 Rust 调用外部 C 函数时,如果可以确认安全,可以通过引用来代替裸指针
3.19.8.10.
P.UNS.FFI.10 当 Rust 函数导出外部函数时,必须从设计上保证被跨线程调用的安全性
3.19.8.11.
P.UNS.FFI.11 如需引用指定为 #[repr(packed)] 内存布局的结构体成员字段要注意合理规避未定义行为
3.19.8.12.
P.UNS.FFI.12 当依赖 C 端传入参数时,需要在文档注释中不变性声明,根据不同的调用场景选择合适的安全抽象方式
3.19.8.13.
P.UNS.FFI.13 自定义数据类型要保证一致的数据布局
3.19.8.14.
P.UNS.FFI.14 在 FFi 中使用的类型应该拥有稳定布局
3.19.8.15.
P.UNS.FFI.15 从外部传入的不健壮类型的外部值要进行检查
3.19.9.
I/O
❱
3.19.9.1.
P.UNS.FIO.01 在使用原始句柄的时候,要注意 I/O 安全性
3.19.10.
Unsafe 代码术语指南
3.20.
no-std
❱
3.20.1.
P.EMB.01 no-std 下必须定义一个Panic行为以确保安全
3.20.2.
P.EMB.02 no-std 下要确保程序中的类型有正确的内存布局
3.21.
I/O
❱
3.21.1.
P.FIO.01 使用 read_to_end/read_to_string方法时注意文件的大小能否一次性读入内存中
3.21.2.
G.FIO.01 文件读取建议使用 BufReader/BufWriter 来代替 Reader/Write
3.22.
Information Security
❱
3.22.1.
P.SEC.01 使用第三方库的时候要确保可信的依赖,小心供应链攻击
3.22.2.
G.SEC.01 代码中不要出现非法 Unicode 字符,也要防范非法 Unicode 字符
3.23.
Others
❱
3.23.1.
G.OTH.01 对于某些场景下不建议使用的方法可以通过配置 clippy.toml 来拒绝
3.23.2.
G.OTH.01 使用标准库中对应的方法计算秒级、毫秒级、微秒级的时间
4.
Appendix
❱
4.1.
A.Development Enviroment
4.2.
B.Test
❱
4.2.1.
Unit Test
4.2.2.
Benchmark Test
4.2.3.
Fuzz Test
4.3.
C.Terminology
4.4.
D.Templates
❱
4.4.1.
rustfmt
4.4.2.
clippy
4.4.3.
deny
4.5.
E.Toolchains
❱
4.5.1.
rustfmt
4.5.2.
noisy-clippy
4.5.3.
cargo-udeps
4.6.
F.Cheat Sheet
❱
4.6.1.
Float
4.7.
G.Guide for Optimizations
4.8.
H.Rustc Flags
4.9.
I.Best Practice
❱
4.9.1.
FAQ for Beginners
4.9.2.
Rust Programming Techniques
4.10.
J.Contribution Guidlines
Light (default)
Rust
Coal
Navy
Ayu
Rust Coding Specification V1.0 beta
G.UNS.PTR.02 禁止将不可变指针手工转换为可变指针