serde 源码解析 | Deserialization篇 第二部分
上篇,已经把反序列化的总体过程描述了一遍,也留下了几个问题,DeserializeSeed
和PhantomData
是什么,EnumAccess
中的variant
方法被visit_enum
调用后,为什么能产生一个__Field
实例呢?
| pub trait DeserializeSeed<'de>: Sized { type Value; fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> where D: Deserializer<'de>; }
pub trait Deserialize<'de>: Sized { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>; }
|
和Deserialize
的区别,就在于用DeserializeSeed
自定义了输出的类型,不必和实现类型一致。
也就是说,对一个DeserializeSeed-thing
调用它的deserialize
去消费一个deserializer
提供的数据,可以返回的是自定义的Value类型。
回忆通常情况下,对Deserialize
的使用,是利用泛型参数,由Result<T>
推断出具体的T类型,再调用对应的deserialze
方法,返回一个T类型的实例,这个过程只有类型参与,属于无状态的反序列化,比如下面的T::deserialize()
| pub fn from_str<'a, T>(s: &'a str) -> Result<T> where T: Deserialize<'a>, { let mut deserializer = Deserializer::from_str(s); let t = T::deserialize(&mut deserializer)?; Ok(t) }
|
但是对于实现了DeserializeSeed
的类型,使用上有所不同,通常是初始化成为一个实例,可以拥有自己的数据,常被当作参数seed
传入一个形如
fn *_seed()的方法,由它调用
seed上的反序列化方法,比如下面的
seed.deserialize(),这个deserialize过程则允许
seed`自身数据参与,所以是个有状态的反序列化过程。
| fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { let val = seed.deserialize(&mut *self.de)?; if self.de.next_char()? == ':' { Ok((val, self)) } else { Err(Error::ExpectedMapColon) } }
|
不妨再来看看,哪些地方存在这样的fn *_seed()
:
SeqAccess
中的next_element_seed
MapAccess
中的next_key_seed
、next_value_seed
、next_entry_seed
EnumAccess
中的variant_seed
VariantAcess
中的newtype_variant_seed
这些方法出现在deserializer
为visitor
提供的集合数据类型中。一个visitor
,只有在实现了visit_seq
、visit_map
、visit_enum
这类方法的前提下,才有机会使用有状态的反序列化。
但在实际工作中,大多数情况的反序列化,都是无状态的,所以给这些fn *_seed()
方法传递的DeserializeSeed-thing
,也就是参数seed
,自然可以没有自己的数据,仅仅把某种类型信息给传递进去。像这种有类型、却没有实际数据的东西,标准库里专门有个类型叫PhantomData
,幽灵数据来表示,编译器不会给他分配内存空间,只用来做类型的推断和方法的关联。
Serde已经为PhantomData
实现DeserializeSeed
,使其成为DeserializeSeed-thing
,直接把PhantomData
传入fn *_seed()
里,就等效于无状态Deserialize
的过程,只有类型参与。
| impl<'de, T> DeserializeSeed<'de> for PhantomData<T> where T: Deserialize<'de>, { type Value = T;
#[inline] fn deserialize<D>(self, deserializer: D) -> Result<T, D::Error> where D: Deserializer<'de>, { T::deserialize(deserializer) } }
|
甚至,因为无状态反序列化太普遍,Serde提供了一种快捷方式,比如next_element_seed
的无状态化版本是next_element
,就直接帮你传入了PhantomData
,使用next_element
时,T就通过表达式左值的类型来推断就OK了。
| fn next_element<T>(&mut self) -> Result<Option<T>, Self::Error> where T: Deserialize<'de>, { self.next_element_seed(PhantomData) }
|
有了这样的基础,再看visit_enum
就清楚了,中间调用match _serde::de::EnumAccess::variant(__data)
时,推断出T的类型是__Field
,也就是使用的variant
版本如下:
| fn variant<__Field>(self) -> Result<(__Field, Self::Variant), Self::Error> where __Field: Deserialize<'de>, { self.variant_seed(PhantomData) }
|
因此PhantomData
是PhantomData<__Field>
的一个“实例”,实现了DeserializeSeed
,传到variant_seed
中叫做seed
,根据PhantomData
默认的DeserializeSeed
的实现,variant_seed
中语句seed.deserialize(deserializer)
的本质就是__Field::deserialize(deserializer)
,于是产生了具体的__Field
值。
嵌套之路
清楚了__Field
的来历之后,不妨再关注一下tuple中的第二项,VariantAccess-thing
,它包含着四个必须实现的方法,概括了可能出现的枚举形态
unit_variant
,比如对应Command::Quit
newtype_variant
,比如对应Command::Rm
tuple_variant
,比如对应Command::SomeCmd(a, b, c)
这种
struct_variant
,比如对应Command::{Get, Set}
一个VariantAccess
可以看做特定领域的deserializer
,这个四个方法和通用的deserialize_*
方法的作用类似,由上层调用,提示接下来的数据应该可以按照什么样的规则去解析。所以这里的Visitor
和VariantAccess
功能上如同一对Deserialize
和Deserializer
,这不就是一层嵌套吗?
举两个例子,这两个简单的match分支,Command::Quit
和Command::Rm
,就分别提示接下来按照unit_variat
和newtype_variant
的规则解析数据。
| (__Field::__field2, __variant) => { _serde::export::Result::map(_serde::de::VariantAccess::newtype_variant::<String>(__variant), Command::Rm) } (__Field::__field3, __variant) => { match _serde::de::VariantAccess::unit_variant(__variant) { _serde::export::Ok(__val) => __val, _serde::export::Err(__err) => { return _serde::export::Err(__err); } }; _serde::export::Ok(Command::Quit) }
|
但是复杂一点的Command::Set
,它调用的是struct_variant
,表明接下来期待的是结构性的枚举。到这里,更明显的嵌套出现了,又新建一个__Field
类型,用来保存Command::Get
中的Key
和Value
的标识符信息。然后派出一个visitor
,可以从SeqAccess
或者MapAccess
类型的数据来构建Command::Get
的实例。
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#[allow(non_camel_case_types)] enum __Field { __field0, __field1, __ignore, } 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 { ... }
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) -> _serde::export::fmt::Result { _serde::export::Formatter::write_str(__formatter, "struct variant Command::Set") } #[inline] fn visit_seq<__A>(self, mut __seq: __A) -> _serde::export::Result<Self::Value, __A::Error> where __A: _serde::de::SeqAccess<'de>, { let __field0 = match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { _serde::export::Ok(__val) => __val, _serde::export::Err(__err) => { return _serde::export::Err(__err); } } { _serde::export::Some(__value) => __value, _serde::export::None => { return _serde::export::Err(_serde::de::Error::invalid_length( 0usize, &"struct variant Command::Set with 2 elements", )); } }; let __field1 = match match _serde::de::SeqAccess::next_element::<String>(&mut __seq) { _serde::export::Ok(__val) => __val, _serde::export::Err(__err) => { return _serde::export::Err(__err); } } { _serde::export::Some(__value) => __value, _serde::export::None => { return _serde::export::Err(_serde::de::Error::invalid_length( 1usize, &"struct variant Command::Set with 2 elements", )); } }; _serde::export::Ok(Command::Set { key: __field0, value: __field1, }) } #[inline] fn visit_map<__A>(self, mut __map: __A) }
const FIELDS: &'static [&'static str] = &["key", "value"]; _serde::de::VariantAccess::struct_variant( __variant, FIELDS, __Visitor { marker: _serde::export::PhantomData::<Command>, lifetime: _serde::export::PhantomData, }, )
|
因为json中struct
和字典表达形式相同,并且key值都包含在序列化数据中,所以不必使用提供的_fields
参数,直接交给deserialize_map
就足够。
| fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value> where V: Visitor<'de>, { de::Deserializer::deserialize_map(self.de, visitor) }
|
deserialize_map
自然检查map的开闭标识,然后给予一个实现了MapAccess
的结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| fn deserialize_map<V>(mut self, visitor: V) -> Result<V::Value> where V: Visitor<'de>, { if self.next_char()? == '{' { let value = visitor.visit_map(CommaSeparated::new(&mut self))?; if self.next_char()? == '}' { Ok(value) } else { Err(Error::ExpectedMapEnd) } } else { Err(Error::ExpectedMap) } }
|
后面的事情,就是CommaSeparated
和visit_map
相互配合产生Command::Get
了,过程类似Enum
和visit_enum
的交互,这里就不再详细一步步跟踪了。
尾声
我们用两章的篇幅介绍了反序列化过程。
第一个关键点,明确角色
Deserialize
观察目标类型,制作Visitor
,调用Deserializer
,交付Visitor
Deserialzier
和被序列化数据打交道,根据Deserialize
的提示,把序列化数据解析成恰当的基础数据结构,交给Visitor
Visitor
根据Deserializer
给的基础数据类型,按既定规则生成目标类型
第二个关键点,集合类型的反序列化
当Deserializer
被提示接下来的数据可能是由集合类型序列化而来时,所谓的恰当的基础数据结构,就是实现了*Access
系列 trait 的结构,代表着某一种特定结构的Deserializer
。其实也就只有四个。
Trait |
Description |
EnumAccess |
重要方法是variant ,一次性调用,返回(T, VariantAccess),判断数据属于哪种枚举 |
VariantAccess |
四个必须方法,一次性调用,解析具体的某种枚举 |
MapAccess |
按照map的风格访问处理已序列化数据,next_key ,next_value 等 |
SeqAccess |
按照seq的风格访问处理已序列化数据,next_element |
他们统一的风格就是都使用了fn *_seed()
的模式,通过DeserializerSeed
,提供有状态反序列化的能力。普通的反序列化场景,往往不需要有状态,因此传入PhantomData
,直接使用无状态反序列化。
Ok,反序列化也介绍到这里吧。如果想要进一步巩固serde,自己写一个data format的Deserializer
和Serializer
吧。下一篇,我们为redis协议写一个基础的序列化工具。