gpt4 book ai didi

rust - 当 Foobar 只有一个字段时,直接反序列化一个 Vec> 为 Vec

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

我得到了一种数据格式,其中包含一系列对象,每个对象都只有一个命名字段 value。我可以在反序列化时删除这层间接寻址吗?

反序列化时,自然表示是

/// Each record has it's own `{ value: ... }` object
#[derive(serde::Deserialize)]
struct Foobar<T> {
value: T,
}

/// The naive representation, via `Foobar`...
#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<Foobar<T>>,
}

虽然 Foobar 没有增加 T 之外的额外成本,但我想在类型级别删除这个间接层:

#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<T>,
}

Foobar 是否可以从 FoobarContainer 中删除,同时仍然使用它进行反序列化?

最佳答案

在一般情况下,没有简单的方法可以进行这种转换。为此,请查看这些现有答案:

第一个是我通常的首选解决方案和 looks like this在这个例子中。


但是,在您的具体案例中,您说:

objects with exactly one named field value

并且您已经确定了一个关键要求:

While Foobar adds no extra cost beyond T

这意味着你可以让 Foobar 有一个 transparent representation并使用 unsafe Rust 在类型之间转换(尽管 not actually with mem::transmute ):

struct FoobarContainer<T> {
values: Vec<T>,
}

#[derive(serde::Deserialize)]
#[repr(transparent)]
struct Foobar<T> {
value: T,
}

impl<'de, T> serde::Deserialize<'de> for FoobarContainer<T>
where
T: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut v: Vec<Foobar<T>> = serde::Deserialize::deserialize(deserializer)?;

// I copied this from Stack Overflow without reading the surrounding
// text that describes why this is actually safe.
let values = unsafe {
let data = v.as_mut_ptr() as *mut T;
let len = v.len();
let cap = v.capacity();

std::mem::forget(v);

Vec::from_raw_parts(data, len, cap)
};

Ok(FoobarContainer { values })
}
}

另见:

关于rust - 当 Foobar 只有一个字段时,直接反序列化一个 Vec<Foobar<T>> 为 Vec<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58492598/

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