Foobar 只有一个字段时,直接反序列化一个 Vec<Foobar<T>> 为 Vec<T>
Deserialize a Vec<Foobar<T>> as Vec<T> directly when Foobar has exactly one field
我得到了一种数据格式,其中包含一系列对象,每个对象只有一个命名字段 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>,
}
是否可以从 FoobarContainer
中删除 Foobar
,同时仍然使用它进行反序列化?
在一般情况下,没有简单的方法可以进行这种转换。为此,请查看这些现有答案:
- How to transform fields during deserialization using Serde?
第一个是我常用的解决方案,在此示例中 looks like this。
但是,在您的具体案例中,您说:
objects with exactly one named field value
并且您确定了一个关键要求:
While Foobar
adds no extra cost beyond T
这意味着你可以让Foobar
有一个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 })
}
}
另请参阅:
我得到了一种数据格式,其中包含一系列对象,每个对象只有一个命名字段 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>,
}
是否可以从 FoobarContainer
中删除 Foobar
,同时仍然使用它进行反序列化?
在一般情况下,没有简单的方法可以进行这种转换。为此,请查看这些现有答案:
- How to transform fields during deserialization using Serde?
第一个是我常用的解决方案,在此示例中 looks like this。
但是,在您的具体案例中,您说:
objects with exactly one named field value
并且您确定了一个关键要求:
While
Foobar
adds no extra cost beyondT
这意味着你可以让Foobar
有一个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 })
}
}
另请参阅: