gpt4 book ai didi

serialization - 为固定大小向量的包装器实现 Decodable

转载 作者:行者123 更新时间:2023-11-29 08:08:12 26 4
gpt4 key购买 nike

背景:serialize crate 未记录,派生 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) 处给出错误

error: failed to find an implementation of trait serialize::serialize::Decodable for [[A, .. 20], .. 20]

最佳答案

由于各种原因,目前不太可能很好地做到这一点:

  • 我们不能在固定长度数组的长度上通用(基本问题)
  • 当前的特征一致性限制意味着我们无法编写自定义 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 .

也可以写一个更“通用”的[T, .. n]使用 macros 解码器实例化每个版本,对递归解码的处理方式进行特殊控制,以允许处理嵌套的固定长度数组(根据 Grid 的要求);这需要更少的代码(尤其是有更多的层,或各种不同的长度),但宏解决方案:

  • 可能更难理解,并且
  • 我给出的那个可能效率较低(为每个固定长度的数组创建了一个新的 array 变量,包括新的 Default s,而上面的非宏解决方案只使用一个 array 因此只为网格中的每个元素调用一次 Default::default)。也许可以扩展到一组类似的递归循环,但我不确定。

关于serialization - 为固定大小向量的包装器实现 Decodable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25348218/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com