gpt4 book ai didi

rust - 如何仅将自定义序列化用于 “stringy”序列化?

转载 作者:行者123 更新时间:2023-12-03 11:44:46 24 4
gpt4 key购买 nike

我最近开始处理自定义序列化/反序列化:https://stackoverflow.com/a/63846824/129805
我只想对JSON和RON使用此自定义的“字符串式”序列化(和des),而对所有二进制序列化(例如bincode)都使用#[derive(Serialisation, ...。 (将两个字节的(100, 200)膨胀为七个或更多字节的"100:200"是毫无意义的浪费。)
我需要在单个可执行文件中执行此操作,因为服务器/服务器的通信将是bincode或protobufs,而客户端/服务器的通信将是JSON。
服务器/服务器和客户端/服务器通信将使用相同的可序列化结构。即我想为所有通信使用单一结构集,但它们应对JSON/RON使用自定义序列化,但对bin/probubufs使用派生序列化。
我怎样才能做到这一点?

更新:
这是通过测试的工作代码:

use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{self, Visitor, Unexpected};
use std::fmt;
use std::str::FromStr;
use regex::Regex;

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct DerivedIncline {
rise: u8,
distance: u8,
}

impl DerivedIncline {
pub fn new(rise: u8, distance: u8) -> DerivedIncline {
DerivedIncline {rise, distance}
}
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct StringyIncline {
rise: u8,
distance: u8,
}

impl StringyIncline {
pub fn new(rise: u8, distance: u8) -> StringyIncline {
StringyIncline {rise, distance}
}
}

impl Serialize for StringyIncline {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&format!("{}:{}", self.rise, self.distance))
}
}

struct StringyInclineVisitor;

impl<'de> Visitor<'de> for StringyInclineVisitor {
type Value = StringyIncline;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a colon-separated pair of integers between 0 and 255")
}

fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let re = Regex::new(r"(\d+):(\d+)").unwrap(); // PERF: move this into a lazy_static!
if let Some(nums) = re.captures_iter(s).next() {
if let Ok(rise) = u8::from_str(&nums[1]) { // nums[0] is the whole match, so we must skip that
if let Ok(distance) = u8::from_str(&nums[2]) {
Ok(StringyIncline::new(rise, distance))
} else {
Err(de::Error::invalid_value(Unexpected::Str(s), &self))
}
} else {
Err(de::Error::invalid_value(Unexpected::Str(s), &self))
}
} else {
Err(de::Error::invalid_value(Unexpected::Str(s), &self))
}
}

}

impl<'de> Deserialize<'de> for StringyIncline {
fn deserialize<D>(deserializer: D) -> Result<StringyIncline, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_string(StringyInclineVisitor)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn serialisation() {
let stringy_incline = StringyIncline::new(4, 3);
let derived_incline = DerivedIncline::new(4, 3);

let json = serde_json::to_string(&stringy_incline).unwrap();
assert_eq!(json, "\"4:3\"");

let bin = bincode::serialize(&derived_incline).unwrap();
assert_eq!(bin, [4u8, 3u8]);
}

#[test]
fn deserialisation() {
let json = "\"4:3\"";
let bin = [4u8, 3u8];

let deserialised_json: StringyIncline = serde_json::from_str(&json).unwrap();
let deserialised_bin: DerivedIncline = bincode::deserialize(&bin).unwrap();

assert_eq!(deserialised_json, StringyIncline::new(4, 3));
assert_eq!(deserialised_bin, DerivedIncline::new(4, 3));
}
}
我想拥有一个 Incline结构,当序列化为JSON时,其作用类似于StringlyIncline;而当序列化为Bincode时,其作用为DerivedIncline。

最佳答案

如果您每天晚上使用并且愿意打开specialization功能,则可以编写一个函数来告诉您通用参数S是否是serde_json::Serializer

trait IsJsonSerializer {
fn is_json_serializer() -> bool;
}

impl<T> IsJsonSerializer for T {
default fn is_json_serializer() -> bool {
false
}
}

impl<W,F> IsJsonSerializer for &mut serde_json::Serializer<W,F> {
fn is_json_serializer() -> bool {
true
}
}
然后,您可以编写 if S::is_json_serializer() {...}。使用此函数,您的序列化函数可以编写为:
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct RawIncline {
rise: u8,
distance: u8,
}

impl Serialize for Incline {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if S::is_json_serializer() {
serializer.serialize_str(&format!("{}:{}", self.rise, self.distance))
} else {
RawIncline{rise:self.rise, distance:self.distance}.serialize(serializer)
}
}
}
然后,您可以对反序列化执行类似的操作。
我想不出没有 specialization功能就可以使类似的东西工作的方法,所以目前仅限于每晚-但我很想看看是否有可能。

关于rust - 如何仅将自定义序列化用于 “stringy”序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63857120/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com