2

I am new to Rust, and am attempting to take a struct returned from a library (referred to as source struct) and convert it into protobuf message using prost. The goal is to take the source struct, map the source struct types to the protobuf message types (or rather, the appropriate types for prost-generated struct, referred to as message struct), and populate the message struct fields using fields from the source struct. The source struct fields are a subset of message struct fields. For example:

pub struct Message {
    pub id: i32,
    pub email: String,
    pub name: String,
}

pub struct Source {
    pub email: Email,
    pub name: Name,
}

So, I would like to take fields from from Source, map the types to corresponding types in Message, and populate the fields of Message using Source (fields have the same name). Currently, I am manually assigning the values by creating a Message struct and doing something like message_struct.email = source_struct.email.to_string();. Except I have multiple Message structs based on protobuf, some having 20+ fields, so I'm really hoping to find a more efficient way of doing this.

gsundberg
  • 437
  • 1
  • 4
  • 14

3 Answers3

3

This is called FRU (functional record update).
This currently works only for structs with the same type and structs with the same type modulo generic parameters.

The RFC-2528 talks about a generalization that would make this work:

struct Foo {
    field1: &'static str,
    field2: i32,
}

struct Bar {
    field1: f64,
    field2: i32,
}

let foo = Foo { field1: "hi", field2: 1 };
let bar = Bar { field1: 3.14, ..foo };

Unfortunately, this has not yet been implemented.

2

You could make a method to create a Message from a Source like this.

impl Message {
    pub fn from_source(source: &Source, id: i32) -> Self {
        Message {
            id: id,
            email: source.email.to_string(),
            name: source.name.to_string(),
        }
    }
}

And then,

let source = // todo
let id = // todo
let message = Message::from_source(&source, id);
Andrew
  • 904
  • 5
  • 17
2

If I understand you correctly you want to generate define new struct based on fields from another. In that case you have to use macros.

https://doc.rust-lang.org/book/ch19-06-macros.html

Also this question (and answer) could be useful for you Is it possible to generate a struct with a macro?

To convert struct values from one to another struct best way is to use From<T> or Into<T> trait.

https://doc.rust-lang.org/std/convert/trait.From.html

Đorđe Zeljić
  • 1,689
  • 2
  • 13
  • 30