serde 源码解析 | 准备篇
最近做一个练习项目,要求利用serde,为Redis Simple Protocol写一个序列化、反序列化工具。
理解Redis Simple Protocol倒是不难,可是这个serde,人都给我看蒙了。尤其在看反序列化过程的时候,心态一度爆炸,写下了这样的感想:
太复杂了
太TM复杂了
想吼想哭想闹
想吃垃圾食品
想一瞬间变成天上乌漆嘛黑的冰雹云
轰他娘的山本联队
最后总算硬着头皮写出了一版。记录下这个过程。
要了解serde,光看文档难度还是太高了,像是读词典小说,文学上想想《哈扎尔辞典》,游戏上想想宫崎英高养起来的大批”魂学家”,就是那种支离破碎的感觉。所以还原为时间顺序,一步步理解起来更容易。官网给出了一个简化的json样例,叫serde-example,我的学习就是基于这份代码。按照下面的步骤,不妨先把环境搭建起来。
build
将仓库克隆到本地,修改cargo.toml、ser.rs、de.rs
三个文件,支持edition-2018,也随意升级一下serde版本,没什么关系。这个时候cargo check
应该可以通过了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [package] name = "serde-example" edition = "2018" version = "0.1.0" authors = ["David Tolnay <dtolnay@gmail.com>"] license = "MIT OR Apache-2.0" description = "An example Serializer and Deserializer data format for Serde" repository = "https://github.com/serde-rs/example-format" documentation = "https://serde.rs/data-format.html" keywords = ["serde"] categories = ["encoding"] publish = false
[dependencies] serde = { version = "1.0.103", features = ["derive"] }
|
| use crate::error::{Error, Result};
|
run
添加src/bin/inspect.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| use serde::{Deserialize, Serialize}; use serde_example::{from_str, to_string};
#[derive(Debug, Serialize, Deserialize)] enum Command { Set { key: String, value: String }, Get { key: String }, Rm(String), Quit, }
fn main() { let cmd = Command::Set { key: "A".to_owned(), value: "42".to_owned(), }; let ser_cmd = to_string(&cmd).unwrap(); let de_cmd: Command = from_str(&ser_cmd).unwrap(); println!( "origin: {:?}\nserialized: {}\ndeserialized: {:?}", cmd, ser_cmd, de_cmd ); }
|
运行cargo run --bin inspect
就会输出
| origin: Set { key: "A", value: "42" } serialized: {"Set":{"key":"A","value":"42"}} deserialized: Set { key: "A", value: "42" }
|
expand derive
还有一份关键的代码,藏在#[derive(Debug, Serialize, Deserialize)]
里,这条语句自动生成一些(很多!)代码,为Command
实现关键的两个序列化trait。
这要借助cargo-expand工具,如果没有先装一下,一般下面两个命令搞定
| $ rustup toolchain install nightly $ cargo install cargo-expand
|
运行cargo expand --bin inspect
,终端输出生成代码。
其中一段类似下面这样,实现的是Serialize
,把它复制到derive_ser.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| const _IMPL_SERIALIZE_FOR_Command: () = { #[allow(unknown_lints)] #[allow(rust_2018_idioms)] extern crate serde as _serde; #[automatically_derived] impl _serde::Serialize for Command { fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { match *self { Command::Set { ref key, ref value } => { ... _serde::ser::SerializeStructVariant::end(__serde_state) } Command::Get { ref key } => { ... _serde::ser::SerializeStructVariant::end(__serde_state) } Command::Rm(ref __field0) => _serde::Serializer::serialize_newtype_variant( __serializer, "Command", 2u32, "Rm", __field0, ), Command::Quit => _serde::Serializer::serialize_unit_variant( __serializer, "Command", 3u32, "Quit", ), } } } };
|
另一段结构像这样,实现的是Deserialize
,把它复制到derive_de.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| const _IMPL_DESERIALIZE_FOR_Command: () = { #[allow(unknown_lints)] #[allow(rust_2018_idioms)] extern crate serde as _serde; #[automatically_derived] impl<'de> _serde::Deserialize<'de> for Command { fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error> where __D: _serde::Deserializer<'de>, { #[allow(non_camel_case_types)] enum __Field { __field0, __field1, __field2, __field3, } struct __FieldVisitor; impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { type Value = __Field; fn expecting(&self, __formatter: &mut _serde::export::Formatter) ... {} fn visit_u64<__E>(self, __value: u64) ... {} fn visit_str<__E>(self, __value: &str) ... {} fn visit_bytes<__E>(self, __value: &[u8]) ... {} } } impl<'de> _serde::Deserialize<'de> for __Field { #[inline] fn deserialize<__D>(__deserializer: __D) ... {} }
struct __Visitor<'de> { marker: _serde::export::PhantomData<Command>, lifetime: _serde::export::PhantomData<&'de ()>, } impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { type Value = Command; fn expecting(&self, __formatter: &mut _serde::export::Formatter) fn visit_enum<__A>(self, __data: __A) -> _serde::export::Result<Self::Value, __A::Error> where __A: _serde::de::EnumAccess<'de>, { match match _serde::de::EnumAccess::variant(__data) { _serde::export::Ok(__val) => __val, _serde::export::Err(__err) => { return _serde::export::Err(__err); } } { (__Field::__field0, __variant) => {...} (__Field::__field1, __variant) => {...} (__Field::__field2, __variant) => {...} (__Field::__field3, __variant) => {...} } } }
const VARIANTS: &'static [&'static str] = &["Set", "Get", "Rm", "Quit"]; _serde::Deserializer::deserialize_enum( __deserializer, "Command", VARIANTS, __Visitor { marker: _serde::export::PhantomData::<Command>, lifetime: _serde::export::PhantomData, }, ) } } };
|
好了,准备工作就这么多。开始受苦吧。