背景:序列化包没有文档,导出Decodable不起作用。我还查看了其他类型的现有实现,并发现难以遵循的代码。
解码过程如何工作,以及如何为此结构实现Decodable?
pub struct Grid<A> {
data: [[A,..GRIDW],..GRIDH]
}
#[deriving(Decodable)]
不起作用的原因是[A,..GRIDW]
没有实现Decodable,并且当在这个crate之外定义两者时,不可能为类型实现特征,这是这里的情况。因此,我能看到的唯一解决方案是手动实现Decodable for Grid。
就我而言,这是
impl <A: Decodable<D, E>, D: Decoder<E>, E> Decodable<D, E> for Grid<A> {
fn decode(decoder: &mut D) -> Result<Grid<A>, E> {
decoder.read_struct("Grid", 1u, ref |d| Ok(Grid {
data: match d.read_struct_field("data", 0u, ref |d| Decodable::decode(d)) {
Ok(e) => e,
Err(e) => return Err(e)
},
}))
}
}
这会在Decodable::decode(d)
错误:未能找到特征的实现 serialize :: serialize :: [[A,.. 20],.. 20]
的可解码
答案 0 :(得分:2)
由于各种原因,目前不太可能做得很好:
trait MyDecodable<D, E> { ... }
(一个用于impl MyDecodable<D, E> for [A, .. GRIDW]
)和一揽子实施GRIDH
来编写自定义impl<A: Decodable<D, E>> MyDecodable<D, E> for A
。这迫使基于特质的解决方案使用中间类型,这使得编译器的类型推断相当不愉快,AFAICT无法满足。因此,目前,我们已经手动实施了。 :(
extern crate serialize;
use std::default::Default;
use serialize::{Decoder, Decodable};
static GRIDW: uint = 10;
static GRIDH: uint = 5;
fn decode_grid<E, D: Decoder<E>,
A: Copy + Default + Decodable<D, E>>(d: &mut D)
-> Result<Grid<A>, E> {
// mirror the Vec implementation: try to read a sequence
d.read_seq(|d, len| {
// check it's the required length
if len != GRIDH {
return Err(
d.error(format!("expecting length {} but found {}",
GRIDH, len).as_slice()));
}
// create the array with empty values ...
let mut array: [[A, .. GRIDW], .. GRIDH]
= [[Default::default(), .. GRIDW], .. GRIDH];
// ... and fill it in progressively ...
for (i, outer) in array.mut_iter().enumerate() {
// ... by reading each outer element ...
try!(d.read_seq_elt(i, |d| {
// ... as a sequence ...
d.read_seq(|d, len| {
// ... of the right length,
if len != GRIDW { return Err(d.error("...")) }
// and then read each element of that sequence as the
// elements of the grid.
for (j, inner) in outer.mut_iter().enumerate() {
*inner = try!(d.read_seq_elt(j, Decodable::decode));
}
Ok(())
})
}));
}
// all done successfully!
Ok(Grid { data: array })
})
}
pub struct Grid<A> {
data: [[A,..GRIDW],..GRIDH]
}
impl<E, D: Decoder<E>, A: Copy + Default + Decodable<D, E>>
Decodable<D, E> for Grid<A> {
fn decode(d: &mut D) -> Result<Grid<A>, E> {
d.read_struct("Grid", 1, |d| {
d.read_struct_field("data", 0, decode_grid)
})
}
}
fn main() {}
也可以写一个更多&#34;泛型&#34; [T, .. n]
解码器使用macros来实例化每个版本,特别控制如何处理递归解码以允许处理嵌套的固定长度数组(根据Grid
的要求);这需要更少的代码(特别是有更多的层,或各种不同的长度),但宏解决方案:
array
变量,包括新的Default
s,而上面的非宏解决方案只使用一个array
,因此只对网格中的每个元素调用一次Default::default
。有可能扩展到一组类似的递归循环,但我不确定。