4 个版本

0.2.1 2021 年 10 月 2 日
0.2.0 2021 年 9 月 19 日
0.1.1 2021 年 7 月 26 日
0.1.0 2021 年 7 月 23 日

#1654 in Rust 模式

MIT/Apache

180KB
4K SLoC

Flexpiler

该包旨在提供一种方式,以便用户可以自定义 Rust 对象的读写格式。目的是减轻希望快速启动自己的项目且不太关心数据存储方式的私有开发者的负担。

目前,该包处于早期阶段,仅支持反序列化形式为 Rust 结构体和枚举的简化形式,其格式与 Rust 自身初始化结构体和枚举的方式相似。

如何使用

该项目使用其姐妹包 flexpiler_derive 来提供 #[derive] 宏。此宏生成代码,使得被推导的结构体/枚举获得对 flexpiler::Deserialize 的实现。从那时起,您可以通过调用 YourType::deserialize(reader_mut_ref) 从字符串或文件读取器中反序列化类型。

extern crate flexpiler;

#[derive(flexpiler::Deserialize)]
struct MyPoint {
    x: i32,
    y: i32,
}

#[test]
fn basic() {
	// Trait that implements deserialize<...>(...)
    use flexpiler::Deserialize;
    // namespace of common flexpiler reader implementations
    use flexpiler::common::reader;

    // Provide data via reading a string
    // You may at this point provide a file handle or similar instead
    let mut reader = reader::String::from(
        "MyPoint{x:5,y:7}"
    );

    // Try and deserialize our object, modifying the reader in the process
    let parse_result = MyPoint::deserialize(&mut reader);
	// flexpiler deserialization ends in a std::result::Result
    let my_point = match parse_result {
        Ok(value) => value,
        Err(error) => {
            assert!(false, "parade() test ended in a failed deserialization:\n{}", error);
            return;
        }
    };

    // Check if our deserialized object contains the correct values for its fields
    assert_eq!(my_point.x, 5);
    assert_eq!(my_point.y, 7);
}

当前限制

最后更新:版本 0.2.0

该项目不支持像我期望的那样多的标准类型。特别是 HashMap<KeyType, DataType> 和各种原始类型目前在我的实现清单中。

Flexpiler目前使用自定义的flexpiler::reader::Trait解析实现,并期望用户将文件读取器、字符串读取器或其他类型的读取器转换为实现了它的类型。该项目应包含各种常见实现,并可能支持从常见的实践类型(如BufReader)到其隐式转换。

目前不支持Rust联合。

该项目目前无法处理泛型。

未来计划

作为一个alpha版crate,该项目的API将在每次“小版本”增量(x.y.z => x.y+1.z)时发生变化。然而,目前从外部使用的所需API遵循即将到来的非明确愿景。

use flexpiler::{Deserialize}

struct CakeFormat {
	// [ some error handling functionality of an unspecified format ]
}

#[derive(flexpiler::Deserialize)]
#[flexpiler_format = CakeFormat]
#[flexpiler_format_style = "{[glazing]}\n{[cream]}\n{[flour_in_grams]}"]
struct MyCustomizedType {
	glazing: std::string,
	cream: MyCreamType,
	flour_in_grams:i32,
}


[#test]
fn test_flexpiler() {
    use flexpiler::Deserialize;
    use flexpiler::common::reader;

    let mut reader = reader::String::from(
        "{\"Strawberry\"}\n{MyCreamType::Vanilla}\n{525}"
    );

    let parse_result = MyCustomizedType::deserialize(&mut reader);
    let my_customized_type = match parse_result {
        Ok(value) => value,
        Err(error) => {
            assert!(false, "test_flexpiler() test ended in a failed deserialization:\n{}", error);
            return;
        }
    };

    assert_eq!(my_customized_type.glazing.as_str(), "Strawberry");
    assert_eq!(my_customized_type.cream, MyCreamType::Vanilla);
    assert_eq!(my_customized_type.flour_in_grams, 525);
}


请注意,该项目目前无法完成此操作。但这正是我们未来努力的方向。

工作原理

本质上,该衍生宏功能创建了一个中间结构体,用于在对象最终构建之前保存您的数据。然后,它从头开始编写整个deserialize函数,包括解析和错误转发,假设每个子类型都有自己的Deserialize实现。

Deserialize已经在flexpiler::common::deserializer中实现,用于各种常见类型,例如i32、std::string。然而,目前对于某些标准类,您需要提供自己的flexpiler::Deserialization实现。

依赖项

~1.5MB
~35K SLoC