#flat #binary-data #type #contiguous-memory #portable #composite #attributes

no-std flatty-portable

Flatty portable 特性和原语

9 个版本

0.1.0-rc.42023年11月8日
0.1.0-rc.22023年8月22日
0.1.0-rc.02023年6月13日
0.1.0-alpha.72023年5月18日
0.1.0-alpha.22022年9月9日

#1353 in Rust 模式


2 个crate中使用 (通过 flatty)

MIT/Apache

59KB
1.5K SLoC

flatty

Crates.io Docs.rs Gitlab CI License

Flat 消息缓冲区,可以直接映射到 Rust 类型,无需打包/解包。

概述

当类型占用单个连续内存区域时,称为 flat 类型。当您需要以二进制数据的形式存储或发送此类对象,同时又有方便的方式访问其内容而无需序列化/反序列化时,此类类型非常有用。

该crate提供基本的 flat 类型以及创建新的用户定义复合 flat 类型的方法(使用 #[flat] 属性宏),这些类型可以像常规 Rust structenum 一样使用。

此外,该crate也可以在不使用 std 的情况下使用,甚至不使用 alloc

概念

转换

可以使用 as_bytes (以及不安全的 as_mut_bytes)从 flat 类型的实例获取二进制表示。还可以将字节转换为 flat 类型,请参阅就地初始化验证

DST

flat 类型可以是动态大小的(如 FlatVec),在这种情况下,它利用 Rust 操作 ?Sized 类型的能力。用户定义的 flat 结构也可以是无大小的(只允许最后一个字段是无大小的)。甚至 flat 枚举也可以是无大小的,但 Rust 尚未原生支持它们,因此其内容只能通过返回包含对原始枚举内容引用的常规枚举的 as_ref/as_mut 方法来访问。

就地初始化

可以像常规 Rust 类型一样实例化有大小类型。但在 DST 的情况下,由于编译时不知道其大小,Rust 不能像往常一样在栈上构造它。相反,我们可以在给定的内存区域上初始化此类类型。

为此,我们可以使用所谓的填充器 - 可以在给定内存上初始化对象的东西。对于有大小类型,其实例也是填充器。

Emplacer 可用于对原始字节应用 new_in_place,或使用 assign_in_place 替换现有结构体内容。此外,某些类型具有默认的 emplacer,可以通过 default_in_place 初始化为默认状态。

验证

并非任何字节的组合都是平面类型的有效表示。例如,Bool 只有两种有效状态:01,或者 FlatVec 的长度不能大于其容量。可以使用 validate 来检查数据是否适用于特定平面类型,或者 from_bytes/from_mut_bytes 也会进行此类检查。

当你信任你的数据时,可以使用不安全的 from_bytes_unchecked/from_mut_bytes_unchecked 跳过验证,但数据无效时这将导致未定义行为(UB)。

可移植性

平面类型保证在具有相同字节序、对齐和地址宽度的平台上具有相同的二进制表示。如果您需要更强的保证,可以使用 Portable 类型 - 它们在 任何 平台上都具有相同的二进制表示,并且始终对齐到字节。要使自己的平面类型可移植,请使用 #[flat(portable = true)]。此外,这也可以用于创建无对齐问题的紧凑平面类型。

示例

您可以在 tests 目录中找到如何创建和使用平面类型的示例。

许可

根据您的选择,许可如下:

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交给包含在该作品中的任何有意贡献,都应如上所述双重许可,而不附加任何额外的条款或条件。

依赖关系

~185KB