#i32 #u8 #serialization #deserialize #convert #convert-images #back

serialize_deserialize_u8_i32

一个Rust库,安全地在u8和i32之间进行转换、前后转换

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
}

无运行时依赖