4 个稳定版本
3.0.0 | 2022年4月20日 |
---|---|
2.0.0 | 2022年4月19日 |
1.0.2 | 2022年4月13日 |
#2241 in 解析器实现
用于 kaydle
23KB
223 行
serde-mobile
该软件包提供创建面向移动的序列和映射访问器的特性和适配器,作为剩余 serde 反序列化器特性的补充,这些特性完全是面向移动的。有关详细信息,请参阅docs.rs。
lib.rs
:
该软件包提供创建面向移动的序列和映射访问器的特性和适配器,作为剩余 serde 反序列化器特性的补充,这些特性完全是面向移动的。
它提供了SeqAccess
,它替代了serde::de::SeqAccess
,以及MapKeyAccess
/ MapValueAccess
,它们共同替代了serde::de::MapAccess
。当您专注于使用移动构造时,这些特性在实现 Deserializer
时通常更容易使用,并有助于确保调用者的正确性。
为了与serde进行交互,它还提供了AccessAdapter
。这个结构体接受任何SeqAccess
或MapKeyAccess
类型,并将其转换为serde::de::SeqAccess
或serde::de::MapAccess
。
示例
在这个示例中,我们感兴趣的是创建一个反序列化器,它从一对`(key, value)`的迭代器中读取并将它们作为映射输出。我们创建了一个`KeyAccess`类型,该类型实现了MapKeyAccess
。我们使用`serde-mobile`的内置SubordinateValue
类型作为我们的MapValueAccess
,因为我们将在键和值访问器中存储迭代器。这最终使得实现更加简单(如果更冗长):一个serde::de::MapAccess
是一个需要单独反序列化键和值的单一类型,因此需要一些不灵活的设计来捕捉键已产生但值未产生的情况。《serde-mobile》,另一方面,将其拆分为一对类型,这样就可以表达正确的状态。
use std::collections::hash_map::{HashMap, IntoIter};
use std::marker::PhantomData;
use serde::de::{
IntoDeserializer,
Error,
DeserializeSeed,
value::{MapAccessDeserializer, Error as SimpleError},
};
use serde::Deserialize;
use serde_mobile::{
MapKeyAccess,
MapValueAccess,
AccessAdapter,
SubordinateValue
};
struct KeyAccess<I, E>{
entries: I,
error: PhantomData<E>,
}
impl<I, K, V, E> KeyAccess<I, E>
where
I: Iterator<Item=(K, V)>
{
fn new<C>(collection: C) -> Self
where C: IntoIterator<IntoIter=I>
{
Self {
entries: collection.into_iter(),
error: PhantomData,
}
}
}
// MapKeyAccess is the key-getting equivalent of serde::de::MapAccess
impl<'de, I, K, V, E> MapKeyAccess<'de> for KeyAccess<I, E>
where
I: Iterator<Item=(K, V)>,
K: IntoDeserializer<'de, E>,
V: IntoDeserializer<'de, E>,
E: Error,
{
type Error = E;
type Value = SubordinateValue<V::Deserializer, Self>;
// notice that next_key_seed takes self by move and returns Self::Value,
// which is a MapKeyAccess. This forces the caller to get a value before
// they can get another key.
fn next_key_seed<S>(mut self, seed: S) -> Result<Option<(S::Value, Self::Value)>, Self::Error>
where
S: DeserializeSeed<'de>
{
self.entries
.next()
.map(|(key, value)| {
seed
.deserialize(key.into_deserializer())
.map(|key| (
key,
SubordinateValue {
value: value.into_deserializer(),
parent: self
}
))
})
.transpose()
}
fn size_hint(&self) -> Option<usize> {
match self.entries.size_hint() {
(min, Some(max)) if min == max => Some(min),
_ => None,
}
}
}
// Normally we'd have to create a separate struct to implement `MapValueAccess`,
// but this pattern is common enough that serde-mobile provides a type called
// `SubordinateValue` that handles this pattern for us.
let serialized = HashMap::from([
("a", 10),
("b", 20),
]);
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Data {
a: i32,
b: i32,
}
let seq_access = KeyAccess::new(serialized);
// use an AccessAdapter to turn a serde-mobile access type
// into a serde access type
let deserializer = MapAccessDeserializer::new(AccessAdapter::new(seq_access));
match Data::deserialize(deserializer) {
Ok(data) => assert_eq!(data, Data { a: 10, b: 20 }),
Err(err) => {
let err: SimpleError = err;
panic!("failed to deserialize")
}
}
依赖
~110–340KB