31个版本
0.1.34 | 2020年8月15日 |
---|---|
0.1.31 | 2020年4月13日 |
0.1.14 | 2020年3月23日 |
#717 in 编码
在 3 crates 中使用
38KB
443 行
在u8和i32之间进行序列化和反序列化
一个Rust库,安全地在u8和i32之间进行转换、前后转换
示例用法(一个也使用serde和bincode的食谱)
假设你在代码中有一个以下自定义图像对象。
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct PhotonImage {
raw_pixels: Vec<u8>,
width: u32,
height: u32,
}
你的 main.rs
可能看起来像这样
use serde::{Deserialize, Serialize};
fn main() {
let photon_image = PhotonImage {
raw_pixels: vec![
134, 122, 131, 255, 131, 131, 139, 255, 135, 134, 137, 255, 138, 134, 130, 255, 126,
125, 119, 255, 131, 134, 129, 255, 137, 134, 132, 255, 130, 126, 130, 255, 132, 125,
132, 255, 122, 142, 129, 255, 134, 135, 128, 255, 138, 120, 125, 255, 125, 134, 110,
255, 121, 122, 137, 255, 141, 140, 141, 255, 125, 144, 120, 255,
],
width: 4,
height: 4,
};
}
你的依赖关系可能看起来像这样
[dependencies]
serde = { version = "1.0.104", features = ["derive"] }
为什么将序列化为i32整数?
有一些应用程序,如SecondState的Rust存储接口库,允许你将对象存储和加载为i32。这个crate允许你将数据序列化为i32,以便你可以利用这些存储机会。
序列化
将 bincode = "^1.2"
和 serialize_deserialize_u8_i32 = "^0.1"
添加到你的依赖关系中。它们看起来可能不是这样的。
[dependencies]
bincode = "^1.2"
serialize_deserialize_u8_i32 = "^0.1"
serde = { version = "1.0.104", features = ["derive"] }
然后也将以下代码添加到你的主函数中以序列化为 i32
use serde::{Deserialize, Serialize};
use serialize_deserialize_u8_i32::s_d_u8_i32;
use bincode;
将以下代码添加到你的主函数中以序列化为 u8
let encoded_u8: Vec<u8> = bincode::serialize(&photon_image).unwrap();
这将产生以下数据结构
[64, 0, 0, 0, 0, 0, 0, 0, 134, 122, 131, 255, 131, 131, 139, 255, 135, 134, 137, 255, 138, 134, 130, 255, 126, 125, 119, 255, 131, 134, 129, 255, 137, 134, 132, 255, 130, 126, 130, 255, 132, 125, 132, 255, 122, 142, 129, 255, 134, 135, 128, 255, 138, 120, 125, 255, 125, 134, 110, 255, 121, 122, 137, 255, 141, 140, 141, 255, 125, 144, 120, 255, 4, 0, 0, 0, 4, 0, 0, 0]
序列化为i32
// Serialize that to i32
let encoded_i32: Vec<i32> = s_d_u8_i32::serialize_u8_to_i32(encoded_u8);
println!("As i32: {:?}", encoded_i32);
产生以下结果
As i32: [1064000000, 1000000000, 1000000134, 1122131255, 1131131139, 1255135134, 1137255138, 1134130255, 1126125119, 1255131134, 1129255137, 1134132255, 1130126130, 1255132125, 1132255122, 1142129255, 1134135128, 1255138120, 1125255125, 1134110255, 1121122137, 1255141140, 1141255125, 1144120255, 1004000000, 1000004000, 2000000000]
为什么将i32反序列化为u8?
这个crate还允许你从SecondState的Rust存储接口库中加载你的i32数据并将其转换回原始的Rust高级对象。
反序列化
// Deserialize back to u8
let encoded_u8_again: Vec<u8> = s_d_u8_i32::deserialize_i32_to_u8(encoded_i32);
println!("As u8 again: {:?}", encoded_u8_again);
产生以下结果
As u8 again: [64, 0, 0, 0, 0, 0, 0, 0, 134, 122, 131, 255, 131, 131, 139, 255, 135, 134, 137, 255, 138, 134, 130, 255, 126, 125, 119, 255, 131, 134, 129, 255, 137, 134, 132, 255, 130, 126, 130, 255, 132, 125, 132, 255, 122, 142, 129, 255, 134, 135, 128, 255, 138, 120, 125, 255, 125, 134, 110, 255, 121, 122, 137, 255, 141, 140, 141, 255, 125, 144, 120, 255, 4, 0, 0, 0, 4, 0, 0, 0]
反序列化回Rust
let decoded: PhotonImage = bincode::deserialize(&encoded_u8_again[..]).unwrap();
println!("As PhotonImage again: {:?}", decoded);
产生以下结果
As PhotonImage again: PhotonImage { raw_pixels: [134, 122, 131, 255, 131, 131, 139, 255, 135, 134, 137, 255, 138, 134, 130, 255, 126, 125, 119, 255, 131, 134, 129, 255, 137, 134, 132, 255, 130, 126, 130, 255, 132, 125, 132, 255, 122, 142, 129, 255, 134, 135, 128, 255, 138, 120, 125, 255, 125, 134, 110, 255, 121, 122, 137, 255, 141, 140, 141, 255, 125, 144, 120, 255], width: 4, height: 4 }
显式地将u8序列化为i32(一个不使用serde或bincode的食谱)
如果您对使用具有最少依赖的高性能数据模型感兴趣,请考虑以下内容。如您从上面的示例中看到,这个库可以以通用的方式促进高级复杂数据类型的存储和检索。当然,这非常简单易用。但是,您可以更进一步,提前自行显式地将您的数据编码为i32。这基本上意味着,您不是创建您数据的通用表示,而是在提前(打开)PhotonImage对象以序列化和分别存储每个内部部分。
为什么您想这样做呢?
这样您就可以构建更高效的密集计算。让我解释一下。如果您将数据作为高级数据类型存储,处理像素的图像处理应用程序将不得不花费时间打包/解包高级对象。
解包是一个执行可能不想要的额外开销。
此外,打包/解包需要您的离散图像处理函数具有依赖项,如serde和bincode。
您仍然可以存储和加载高级对象。只需在不同的Rust/Wasm可执行文件中这样做。如果您想要最大的效率,并且您有符合条件的数据(例如像素数组[u8]
),您可以将这些数据存储为Wasm虚拟机可以原生处理的方式(没有任何serde & bincode开销)。以下是一个仅执行像素处理的离散应用程序的示例,具有最小的开销Cargo.toml
[dependencies]
serialize_deserialize_u8_i32 = "^0.1"
rust_storage_interface_library = "^0.1"
Rust/Wasm像素处理函数
use serialize_deserialize_u8_i32::s_d_u8_i32;
use rust_storage_interface_library::ssvm_storage;
接收特定图像的i32存储键,转换图像并返回新生成的(solarized)图像的新存储键
#[no_mangle]
pub extern fn solarize_the_pixels(_orig_image_location: i32) -> i32 {
// Load your data from the storage layer (u8 pixels are stored at a compression rate of 3:1)
let i32_vec: Vec<i32> = ssvm_storage::load::load_as_i32_vector(_orig_image_location);
// Quickly convert it to pixel data
let mut individual_pixels: Vec<u8> = s_d_u8_i32::deserialize_i32_to_u8(i32_vec);
// Process each pixel directly inside the VM
for pixel in individual_pixels.iter_mut() {
if 200 as i32 - *pixel as i32 > 0 {
*pixel = 200 - *pixel;
}
}
// Pack the u8 pixels back into i32s (compressing 3:1)
let new_encoded_image: Vec<i32> = s_d_u8_i32::serialize_u8_to_i32(individual_pixels);
// Save the solarized image to the storage location and retrieve its storage key
let new_image_storage_key: i32 = ssvm_storage::store::store_as_i32_vector(new_encoded_image);
// Pass the storage key of the solarized image back to the calling code
new_image_storage_key
}