#键值 #阀门 #序列化 #反序列化 #VDF #数据文件 #serde

vdflex

使用 Serde 解析 Valve 数据文件 (VDF,也称为 KeyValues) 格式的序列化和反序列化库

2 个版本

0.1.1 2024年6月26日
0.1.0 2024年6月24日

#521 in 解析器实现

MIT 许可证

79KB
1.5K SLoC

VDFLex   Crates.io GitHub Actions Workflow Status Docs.rs GitHub

VDFLex 是一个用于解析 Valve 数据文件格式(VDF,也称为 KeyValues)的序列化和反序列化库,使用 serde。VDF 或更普遍的 KeyValues 是 Valve 为 Steam 和 Source 引擎开发的数据格式。

LightmappedGeneric
{
    $basetexture "myassets\gravel01"
    $surfaceprop gravel
}

安装

将以下内容添加到您的项目 Cargo.toml

[dependencies]
serde = { version = "1.0.0", features = ["derive"] }
vdflex = "0.1.1"

功能标志

  • default: 无功能
  • preserve_order: 保留条目插入顺序

快速入门

use std::collections::BTreeMap;
use std::hash::Hash;
use serde::Serialize;

#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize)]
struct AppId(u32);

#[derive(Serialize)]
#[serde(rename_all = "PascalCase")]
struct AppBuild {
    #[serde(rename = "AppID")]
    app_id: AppId,
    desc: String,
    content_root: String,
    build_output: String,
    depots: BTreeMap<AppId, Depot>
}

#[derive(Serialize)]
struct Depot {
    #[serde(rename = "FileMapping")]
    file_mappings: Vec<FileMapping>
}

#[derive(Serialize)]
struct FileMapping {
    #[serde(rename = "LocalPath")]
    local_path: String,
    #[serde(rename = "DepotPath")]
    depot_path: String,
}

fn main() -> vdflex::Result<()> {
    let mut depots = BTreeMap::new();
    depots.insert(AppId(1234), Depot {
        file_mappings: vec![FileMapping { 
            local_path: String::from("*"),
            depot_path: String::from("."),
        }],
    });
    
    let build_script = AppBuild {
        app_id: AppId(1234),
        desc: String::from("My SteamPipe build script"),
        content_root: String::from("..\\assets\\"),
        build_output: String::from("..\\build\\"),
        depots,
    };
    
    let text: String = vdflex::kv_to_string("AppBuild", &build_script)?;
    println!("{text}");
    // "AppBuild"
    // {
    //     "AppID" "1234"
    //     "BuildOutput" "..\build\"
    //     "ContentRoot" "..\assets\"
    //     "Depots"
    //     "Desc" "My SteamPipe build script"
    //     {
    //         "1234"
    //         {
    //             "FileMapping"
    //             {
    //                 "DepotPath" "."
    //                 "LocalPath" "*"
    //             }
    //         }
    //     }
    // }
  

    Ok(())
}

支持的类型

KeyValues 定义得非常糟糕,但通常只支持字符串和多映射(对象)。VDFLex 尝试支持每个 Rust 类型,但并非所有类型都一定有“惯用”或“有用”的表示。以下是 VDFlex 支持的类型以及它们在 KeyValues 中的表示

类型 说明
bool 序列化为 10
整数 KeyValues 通常不支持 i128u128
f32/f64 某些实现只支持 f32。非有限浮点数也支持得不好。
char/String/str -
Option KeyValues 没有与 null 等效的类型,因此 Some<T> 被表示为 T,而 None 则直接省略
单元/单元结构体 序列化方式与 None 相同
单元变体 表示为与变体名称匹配的字符串
新类型结构体 表示为封装类型
新类型变体 表示为一个对象,该对象将变体名称映射到封装类型
序列/元组/元组结构体 通过重复序列中的每个元素的关键字来表示
元组变体 通过包含元组字段的序列的映射来表示,使用变体名称作为键
映射/结构体 通过对象表示(花括号包围的关键字值对列表)
结构体变体 表示为一个对象,将变体名称映射到其字段的表示

限制

  • Bytes 类型不受支持,因为在 KeyValues 中没有明确的方式来表示二进制数据。
  • 序列很奇怪。无法序列化顶层或嵌套的序列。有关更多信息,请参阅 Error::UnrepresentableSequence

缺失的功能

此库处于早期阶段。因此,许多功能尚未实现。一些缺失的功能包括

  • 反序列化
    • 文本解析
    • 转换为 Rust 类型
  • Object 提供更简单的 API
  • 创建 Objectkeyvalues!
  • 条件标签
    • ser::Formatter API 支持条件标签,但 serde API 不支持此功能。
  • #base#include 指令
    • ser::Formatter API 支持宏格式化,但 serde API 将宏视为普通字段。

许可证

此库根据 MIT 许可证授权(https://opensource.org/license/MIT)。

依赖项

~0.4–1.1MB
~24K SLoC