开源地址:https://github.com/mzaks/mojo-flx

FlexBuffers 是由 Wouter van Oortmerssen 设计的一种数据序列化格式,是 FlatBuffers 项目的一部分。 该格式可以表示由属性值映射和数组组成的数据对象(与 JSON 相同),有关更多信息,请参阅支持的值类型段落。
FlexBuffers 格式支持随机值访问,不需要解析(如 JSON、YAML、TOML 和其他基于文本的格式)或解压缩(如 MsgPack、CBOR 和其他紧凑的二进制格式)。此外,缓冲区中的数据是对齐的,无需不必要的内存副本即可读取。
支持的值类型
FlexBuffers 支持 Int、UInt 和 Float 类型的数值,宽度为 1、2、4 和 8 字节。 该格式允许 null 值 (None)、布尔值 (True / False)、字符串值和 blob(字节字符串)值。所有提到的值都可以存储在向量中,也可以作为值存储在映射中。允许不受任何限制地嵌套映射和矢量。
向量存储其大小,并允许根据提供的索引访问随机值。这甚至适用于异构类型。
映射基于两个向量,一个是排序字符串键的向量,另一个是异构值的向量。随机值加速基于对键向量中给定键的二进制搜索,并根据找到的键索引从值向量中读取值。这允许在不解压缩和瞬态内存分配的情况下进行值访问。
将 Mojo 值转换为 FlexBuffer
通过使用便利函数,我们可以从 、 和值构造 FlexBuffers。使用 a 和 a 长度(Int 类型)调用函数将构造一个向量。 函数从 a 和 a 长度生成 FlexBuffer。 生成表示该值的 FlexBuffer。flxStringIntSIMD[DType, 1]flxDTypePointerflx_blobDTypePointer[DType.uint8]flx_nullnull
例子:
from flx import flx, flx_blob, flx_null
let b0 = flx_null()
let b1 = flx(25)
let b2 = flx("hello world")
let b3 = flx[DType.bool](True)
let b4 = flx[DType.float32](43.1)
var blob = DynamicVector[UInt8](100)
for i in range(100):
blob.push_back(5)
let b5 = flx_blob(blob.data, len(blob))
var v = DynamicVector[UInt16](1000)
for i in range(1000):
v.push_back(i)
let b6 = flx(DTypePointer[DType.uint16](v.data), len(v))
构建矢量和映射
为了构建矢量和映射,用户需要使用 和 结构。FlxVecFlxMap
您可以在下面找到一个示例,其中我们生成一个基于列的数据帧,其中命名列作为向量映射:
from flx import FlxMap
try:
let df_cb = FlxMap()
.vec("name")
.add("Maxim")
.add("Leo")
.add("Alex")
.up_to_map()
.vec("age")
.add(42)
.add(43)
.add(28)
.up_to_map()
.vec("friendly")
.add[DType.bool](False)
.add[DType.bool](True)
.add[DType.bool](True)
.finish()
except e:
print("Unexpected error", e)
我们可以构造相同的数据帧,但基于行作为映射向量:
from flx import FlxVec
try:
let df_rb = FlxVec()
.map()
.add("name", "Maxim")
.add("age", 42)
.add[DType.bool]("friendly", False)
.up_to_vec()
.map()
.add("name", "Leo")
.add("age", 43)
.add[DType.bool]("friendly", True)
.up_to_vec()
.map()
.add("name", "Alex")
.add("age", 28)
.add[DType.bool]("friendly", True)
.finish()
except e:
print("Unexpected error", e)
从 FlexBuffers 读取值
给定一个指向 FlexBuffer 的开头和长度的 DTypePointer[DType.uint8],我们可以实例化一个可用于访问缓冲区内部值的结构。FlxValue
用户可以通过调用以下方法之一来检查 的类型:FlxValue
- is_nul
- is_a[D: DType]
- is_map
- is_vec
- is_string
- is_blob
- is_int
- is_float
- is_bool
用户可以使用以下方法之一实现价值:
- getD: DType raises -> SIMD[D, 1]
- int(self) raises -> Int
- float(self) raises -> Float64
- string(self) raises -> String
- blob(self) raises -> (DTypePointer[DType.uint8], Int)
下面,您可以找到一个示例,说明如何从上面描述的基于列的数据帧中读取值:
let value = FlxValue(df_cb)
print(value["name"][0].string()) # Maxim
print(value["age"][0].string()) # 42
print(value["friendly"][0].get[DType.bool]()) # False
下面是用于读取基于行的数据帧的代码片段:
let value = FlxValue(df_rb)
print(value[0]["name"].string()) # Maxim
print(value[0]["age"].string()) # 42
print(value[0]["friendly"].get[DType.bool]()) # False
注意:FlxValue 的当前实现不包含边界检查,因此可以认为读取潜在的恶意缓冲区是不安全的。我们希望在未来实现 FlxValue 的安全变体。