反序列化Vec Foobar T.如Vec T所示.直接在Foobar仅有一个字段时 [英] Deserialize a Vec<Foobar<T>> as Vec<T> directly when Foobar has exactly one field

查看:108
本文介绍了反序列化Vec Foobar T.如Vec T所示.直接在Foobar仅有一个字段时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到了一种数据格式,其中包含一系列对象,每个对象恰好具有一个命名字段value.反序列化时能否删除此间接层?

I'm given a data-format that includes a sequence of objects with exactly one named field value each. Can I remove this layer of indirection while deserializing?

反序列化时,自然表示为

When deserializing, the natural representation would be

/// 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外没有增加任何额外成本,但我想在类型级别上删除此间接层:

While Foobar adds no extra cost beyond T, I'd like to remove this layer of indirection at the type-level:

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

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

Can Foobar be removed from FoobarContainer, while still using it using deserialization?

推荐答案

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

In the general case, there's no trivial way to make this transformation. For that, review these existing answers:

第一个是我的常规解决方案,看起来像这样.

The first is my normal go-to solution and looks like this in this example.

但是,在您的特定案例中,您说:

However, in your specific case, you say:

只具有一个命名字段值的对象

objects with exactly one named field value

您已经确定了一项关键要求:

And you've identified a key requirement:

虽然Foobar除了T之外没有增加任何额外成本

While Foobar adds no extra cost beyond T

这意味着您可以使Foobar具有

This means that you can make Foobar have a transparent representation and use unsafe Rust to transmute between the types (although 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 })
    }
}

另请参阅:

这篇关于反序列化Vec Foobar T.如Vec T所示.直接在Foobar仅有一个字段时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆