1 个不稳定版本
0.1.7 | 2023年4月14日 |
---|---|
0.1.6 |
|
#757 in 编码
100KB
2K SLoC
Rust对象格式 (.rof)
Rust对象格式允许将Rust对象序列化到一个与原始对象非常相似的文本格式文件中。它还允许轻松地在不同的编程语言之间传输对象,因为对象可以在各自的编程语言中创建,序列化为字符串,发送到另一种编程语言,然后反序列化并再次使用。
简而言之,这是一个可以将Rust对象序列化和反序列化为字符串的库,这允许在分离的编程语言之间简单保存和传输Rust对象。
cargo add rof-rs
高级API
#[derive(RofCompat)]
enum SongGenre {
ROCK,
POP,
HIPHOP,
RAP,
JAZZ,
COUNTRY,
HEAVYMETAL,
EDM,
CLASSICAL,
}
#[derive(RofCompat)]
struct Song {
song_title: String,
song_author: String,
timestamp: usize,
song_genre: SongGenre
}
fn main() {
let mut song =
Song::load_from_file("C:\\songs\\song_32.rof");
song.timestamp += 1; // Increment the timestamp by 1
song.save_to_file(
"C:\\songs\\song_32.rof",
true /* pretty print option, adds tabs, spaces and newlines to make the file more human-readable, but will not change the data itself in any way */,
)
.expect("Could not save song to a file");
}
高级API可以通过使用RofCompat
宏实现RofCompat
特质。这个RofCompat
特质允许您将对象反序列化为低级别的DataValue
结构,然后可以将其保存到文件中。RofCompat
特质还可以将低级别数据值结构反序列化回其原始形式。此外,RofCompat
特质还提供了其他实用函数,例如:
- serialize_to_string(&self, pretty_print: bool) -> String {}
- deserialize_from_string(serialized_rof: &str) -> Self {}
- as_rof(&self) -> Rof {}
- load_from_file(file_path: &str) -> Self {}
- save_to_file(&self, file_path: &str, pretty_print: bool) -> Result<(), ()> {}
几乎任何结构或枚举都可以通过使用其 derive 宏在这些要求下实现RofCompat
特质:
- 所有 RofCompat 对象都必须实现
Default
属性 - 由于可能在未来解决的某些技术原因,无法序列化类似“对象”的结构和枚举值,例如数组(不是vecs)、切片、元组和其它。这些不可序列化的属性将简单地由 derive 宏忽略,如果您想实现它们,不幸的是您将不得不手动实现
RofCompat
特质。
如上所述,您可以手动实现RofCompat
,如下面的示例所示,建议在尝试之前阅读低级API。这允许您更精确地控制您的结构/枚举在低级形式中的表示方式。
#[derive(Default)]
struct Color {
r: u8,
g: u8,
b: u8,
}
impl RofCompat for Color {
fn serialize(&self) -> Box<dyn DataValue> {
Box::new(DataValueInteger::U32(
65536 * (self.r as u32) + 256 * (self.g as u32) + (self.b as u32),
))
}
fn deserialize(rof_object: Box<dyn DataValue>) -> Self {
let color_int: u32 = rof_object.as_u32();
Self {
r: (color_int % 16_777_216 / 65_536) as u8,
g: (color_int % 65_536 / 256) as u8,
b: (color_int % 256) as u8,
}
}
}
let mut color = Color::load_from_file("C:\\example_objects\\color.rof");
color.r = (color.r + 1) % 255;
color
.save_to_file(
"C:\\example_objects\\color.rof",
true,
)
.expect("Could not save color to file");
实用函数是基于这两个函数为您实现的。正如您所看到的,现在存储的数据要简洁得多,这是一个很好的例子,即使不是总是必要的,但有时手动实现RofCompat
也是一个好主意。
与低级API不同,使用RofCompat
trait不需要对内部系统的工作方式有太多了解,并且可以快速设置。
低级API
Rof
对象负责在Rof中对所有文件的序列化和反序列化,并支持高级RofCompat
trait。您可以如下定义一个新的Rof
。
// Load computer file as a rof
let computer_rof =
Rof::load_from_file("C:\\example_objects\\computer.rof");
// Convert the rof to a struct structure
let mut computer_structure = computer_rof.get_object().as_struct_structure();
let computer_name: String = match computer_structure.get("computer_name") {
Some(loaded_computer_name) => loaded_computer_name.as_string(),
None => String::default(), // ""
};
let mut computer_ram: usize = match computer_structure.get("computer_ram") {
Some(loaded_computer_ram) => loaded_computer_ram.as_usize(),
None => usize::default(), // 0
};
let computer_type: ComputerType = match computer_structure.get("computer_type") {
Some(loaded_computer_type) => match loaded_computer_type.as_enum_structure().0.as_ref()
{
"windows" => ComputerType::WINDOWS,
"linux" => ComputerType::LINUX,
"macos" => ComputerType::MACOS,
"reactos" => ComputerType::REACTOS,
_ => ComputerType::REACTOS,
},
None => ComputerType::default(),
};
// Print out the parsed computer
println!(
"Loaded {:?} Computer, named {} with {}gb of ram",
computer_type, computer_name, computer_ram
);
// Modify the computer
computer_ram += 1;
// Convert the computer back into a struct structure
let computer_struct_properties: Vec<Property> = vec![
Property::new(
String::from("computer_name"),
Box::new(DataValueString::new(computer_name)), // OR computer_name.serialize()
),
Property::new(
String::from("computer_ram"),
Box::new(DataValueInteger::USIZE(computer_ram)), // OR computer_ram.serialize()
),
Property::new(
String::from("computer_type"),
Box::new(DataValueEnum::new(
match computer_type {
ComputerType::WINDOWS => "windows",
ComputerType::LINUX => "linux",
ComputerType::MACOS => "macos",
ComputerType::REACTOS => "reactos",
}
.to_string(),
Vec::new(),
)),
),
];
let computer_struct_structure = DataValueStruct::new(computer_struct_properties);
// Save rof to computer file
// Must create a new rof object, becausue the .get_object() function returns an immutable reference
Rof::new(Box::new(computer_struct_structure))
.save_to_file(
"C:\\example_objects\\computer.rof",
true,
)
.expect("Could not save computer to file");
低级API对任何想要使用它的人来说都是可用的,尽管推荐使用高级RofCompat
API,因为它更易读,需要更少的样板代码,并且更适合初学者。
依赖项
~255–700KB
~17K SLoC