背景:序列化 crate 未记录,派生的Decodable不起作用。我还查看了其他类型的现有实现,并发现难以理解的代码。
解码过程如何工作,以及如何为此结构实现Decodable?
pub struct Grid<A> {
data: [[A,..GRIDW],..GRIDH]
}
#[deriving(Decodable)]
不起作用的原因是[A,..GRIDW]
没有实现Decodable,并且当两个类型都在此 crate 之外定义时,不可能为类型实现特征,在这种情况下就是这种情况。因此,我看到的唯一解决方案是手动实现Grid的Decodable。而据我所知
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)
一个错误最佳答案
由于多种原因,目前尚无法很好地做到这一点:
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() {}
playpen。
还可以通过使用macros实例化每个版本来编写一个更“通用”的
[T, .. n]
解码器,并通过特殊控制方式来处理递归解码,以允许处理嵌套的定长数组(这是Grid
的要求);这需要较少的代码(尤其是具有更多的层,或者具有各种不同的长度),但是需要使用宏解决方案:array
)都创建了一个新的Default
变量,而上述非宏解决方案仅使用一个array
,因此仅对其中的每个元素调用Default::default
一次网格)。可能可以扩展到一组类似的递归循环,但是我不确定。 关于serialization - 为固定大小的向量周围的包装器实现Decodable,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25348218/