Define and implement PcdSerializable trait

This commit is contained in:
Sosthene 2025-06-24 17:10:41 +02:00 committed by Nicolas Cantu
parent f2a51aa6af
commit 132565e0b5

View File

@ -27,6 +27,112 @@ use crate::{
pub const PCD_VERSION: u8 = 1; pub const PCD_VERSION: u8 = 1;
pub(crate) const ZSTD_COMPRESSION_LEVEL: i32 = zstd::DEFAULT_COMPRESSION_LEVEL; pub(crate) const ZSTD_COMPRESSION_LEVEL: i32 = zstd::DEFAULT_COMPRESSION_LEVEL;
pub trait PcdSerializable {
fn serialize_to_pcd(&self) -> Result<Vec<u8>>;
fn deserialize_from_pcd(data: &[u8]) -> Result<Self> where Self: Sized;
}
impl PcdSerializable for serde_json::Value {
fn serialize_to_pcd(&self) -> Result<Vec<u8>> {
let mut compressed = Vec::new();
let mut encoder = zstd::stream::Encoder::new(&mut compressed, ZSTD_COMPRESSION_LEVEL)?;
encoder.write_all(&[PCD_VERSION])?;
encoder.write_all(&[DataType::Json as u8])?;
serde_json::to_writer(&mut encoder, self)?;
encoder.finish()?;
Ok(compressed)
}
fn deserialize_from_pcd(data: &[u8]) -> Result<Self> {
let mut decompressed = Vec::new();
zstd::stream::copy_decode(data, &mut decompressed)?;
if decompressed.len() < 3 {
return Err(Error::msg("Invalid data: too short"));
}
let version = decompressed[0];
let data_type = DataType::try_from(decompressed[1])?;
match (version, data_type) {
(PCD_VERSION, DataType::Json) => {
let json_bytes = &decompressed[2..];
let json_string = String::from_utf8(json_bytes.to_vec())?;
Ok(serde_json::from_str(&json_string)?)
},
_ => Err(Error::msg("Invalid version or data type"))
}
}
}
impl PcdSerializable for FileBlob {
fn serialize_to_pcd(&self) -> Result<Vec<u8>> {
let mut compressed = Vec::new();
let mut encoder = zstd::stream::Encoder::new(&mut compressed, ZSTD_COMPRESSION_LEVEL)?;
encoder.write_all(&[PCD_VERSION])?;
encoder.write_all(&[DataType::FileBlob as u8])?;
let type_len = self.r#type.as_bytes().len() as u8;
encoder.write_all(&[type_len])?;
encoder.write_all(self.r#type.as_bytes())?;
encoder.write_all(&self.data)?;
encoder.finish()?;
Ok(compressed)
}
fn deserialize_from_pcd(data: &[u8]) -> Result<Self> {
let mut decompressed = Vec::new();
zstd::stream::copy_decode(data, &mut decompressed)?;
if decompressed.len() < 4 {
return Err(Error::msg("Invalid data: too short"));
}
let version = decompressed[0];
let data_type = DataType::try_from(decompressed[1])?;
match (version, data_type) {
(PCD_VERSION, DataType::FileBlob) => {
let type_len = decompressed[2] as usize;
let type_str = String::from_utf8(decompressed[3..3+type_len].to_vec())?;
let data = decompressed[3+type_len..].to_vec();
Ok(FileBlob { r#type: type_str, data })
},
_ => Err(Error::msg("Invalid version or data type"))
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DataType {
FileBlob = 0,
Json = 1,
}
impl TryFrom<u8> for DataType {
type Error = Error;
fn try_from(value: u8) -> Result<Self> {
match value {
0 => Ok(DataType::FileBlob),
1 => Ok(DataType::Json),
_ => return Err(Error::msg(format!("Unknown data type: {}", value))),
}
}
}
#[derive(Serialize, Deserialize)]
pub struct FileBlob {
pub r#type: String,
pub data: Vec<u8>,
}
#[derive(Debug, Default, Clone, Deserialize, Tsify)] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)] #[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Member { pub struct Member {
@ -110,12 +216,6 @@ impl Member {
} }
} }
#[derive(Serialize, Deserialize)]
pub struct FileBlob {
pub r#type: String,
pub data: Vec<u8>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Tsify)] #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)] #[tsify(into_wasm_abi, from_wasm_abi)]
pub struct Pcd(BTreeMap<String, Vec<u8>>); pub struct Pcd(BTreeMap<String, Vec<u8>>);