< 返回版块

ccyanxyz 发表于 2020-06-28 23:50

接触Rust不久,想写点东西练练手,今天遇到一个结构体问题,请各位大佬指点!

我有这样几个结构体

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub name: String,
    pub timestamp: u64,
    pub age: u8,
}

#[derive(Debug)]
pub struct RawInfo2 {
    pub name: String,
    pub timestamp: u64,
    pub first_name: String,
    pub last_name: String,
}

我需要将结构体RawInfo1,RawInfo2对象转换为统一的Info结构体对象,因为这里RawInfo结构体中的元素其实是Info的一个超集,这种情况下,除了通过实现From/Into Trait来转换之外,有没有其他更方便更快的方式?

评论区

写评论
作者 ccyanxyz 2020-06-30 22:27

写成这样的话,还能用serde_json去deseralize数据到结构体吗?

这里的RawInfo1, RawInfo2可能是我在两个不同的数据源获取到的数据通过serde_deserialize出来的,但是我的上层应用只需要name和timestamp这两个字段,所以想要统一一下。比如:

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug, Deserialize)]
pub struct RawInfo1 {
    #[serde(rename = "info1-name")]
    pub name: String,
    #[serde(rename = "info1-ts")]
    pub timestamp: u64,
    pub age: u8,
}

#[derive(Debug, Deserialize)]
pub struct RawInfo2 {
    #[serde(rename = "info2-name")]
    pub name: String,
    #[serde(rename = "info2-ts")]
    pub timestamp: u64,
    pub first_name: String,
}

我现在的做法就是从第一个数据源获取到数据后先deserialize到RawInfo1,然后给Info实现一个From:

impl From<RawInfo1> for Info {
    fn from(item: RawInfo1) -> Info {
        Info {
            name: item.name,
            timestamp: item.timestamp,
        }
    }
}

现在这样的话我每对接一个数据源,就要去实现一个From,所以我想知道的是这种情况下有没有什么更方便的实现方式(减少代码量/提高效率)?

--
👇
Neutron3529: 如果你熟悉Rust的ZCA的话

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub name: String,
    pub timestamp: u64,
    pub age: u8,
}

可以直接改成

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub info: Info,
    pub age: u8,
}

这是一个ZCA,但代价是以后调用RawInfo1的name的时候只能写x.info.name而非x.name了

当然你可以impl一个标inline的trait,让x.name()返回x.info.name

这是另一个ZCA

Nalleyer 2020-06-30 10:42

zero cost abstraction?看了半天才知道是说这个

Neutron3529 2020-06-29 21:47

就是传说中那种哪怕这么写了,性能也等价于手写的最优算法的那种优化(……)

如果是动态类型,你写pub info: Info之后,在你调用a.info.name的时候,程序必须先通过a,找到a->info,再找到a->info->name(两个指针)

而Rust是静态类型,a.name无非一个a的基址+offset,不必多一次取指针,计算a.info.name跟计算a.name的步骤是一样的。

--
👇
malefooo: 你说的ZCA相当于组合吧

--
👇
Neutron3529: 如果你熟悉Rust的ZCA的话

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub name: String,
    pub timestamp: u64,
    pub age: u8,
}

可以直接改成

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub info: Info,
    pub age: u8,
}

这是一个ZCA,但代价是以后调用RawInfo1的name的时候只能写x.info.name而非x.name了

当然你可以impl一个标inline的trait,让x.name()返回x.info.name

这是另一个ZCA

malefooo 2020-06-29 18:13

你说的ZCA相当于组合吧

--
👇
Neutron3529: 如果你熟悉Rust的ZCA的话

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub name: String,
    pub timestamp: u64,
    pub age: u8,
}

可以直接改成

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub info: Info,
    pub age: u8,
}

这是一个ZCA,但代价是以后调用RawInfo1的name的时候只能写x.info.name而非x.name了

当然你可以impl一个标inline的trait,让x.name()返回x.info.name

这是另一个ZCA

Neutron3529 2020-06-29 00:50

如果你熟悉Rust的ZCA的话

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub name: String,
    pub timestamp: u64,
    pub age: u8,
}

可以直接改成

#[derive(Debug)]
pub struct Info {
    pub name: String,
    pub timestamp: u64,
}


#[derive(Debug)]
pub struct RawInfo1 {
    pub info: Info,
    pub age: u8,
}

这是一个ZCA,但代价是以后调用RawInfo1的name的时候只能写x.info.name而非x.name了

当然你可以impl一个标inline的trait,让x.name()返回x.info.name

这是另一个ZCA

1 共 5 条评论, 1 页