Constructing a struct

I have 10 data members in my struct like this.

struct s
    var1: u16,
    var2: u32,
    var3: u8,
    var10: u64,   

And I need to create a new instance from a huge bytearray(which is an ELF binary actually).

I wrote a constructor(new()) for this. In the end, I send back a Ok(s{...}) to the caller. I need to populate the elements first. Should I have 10 local variables first, populate them and then do the following:

Ok(s{var1: local_var1, var2: local_var2, ...., var10: local_var10})

Is there a way to avoid creating these local variables? Just by using something like self.var1 = <value>, self.var2 = <value> etc.,

I understand that new() is not like C++'s constructor where we will be operating on an object for which memory is already allocated, is there any way out?

Because if the structure has 20 variables, I am currently creating 20 local variables in new() and then in the end creating the instance. Is there a way which I am missing?

Thanks a lot!

If your local variables are named the same you can just use;

Ok(s{var1, ...

You can alternatively place whatever expression inside each field of the constructor. Which get evaluated in order you write them. Expressions can include returns (including through ?);

Ok(s{var1: { 1+1 }, ...

You could define the struct a default value (you can #[derive(Default)] or implement manually) and then work with fields individually. The reason you can't define certain fields individually is to prevent partial initialization of the struct.

If you'd like to anyway, it's possible to initialize with MaybeUninit but it can easily lead to UB for certain types.

Are you trying to read an ELF header or something? If so, you can use the C approach where you declare your struct to be bit-for-bit identical to how it is laid out in the file, then do a pointer cast to reinterpret the bytes as a *const s. That way you don't need to deserialize each field individually, and it'll be perfectly safe assuming your struct is some dumb data type containing integers (assuming you do bounds checks and everything).

There are also tools like binread which will generate the necessary deserializing code for you.

You can't do this like in C or C++ because there's no such thing as a half-initialized struct in Rust. You must initialize all its members at once using an object literal (or another constructor which itself has the object literal).

Unless it offends your aesthetic sense, I wouldn't hesitate to set local values, and then construct the struct with them. Especially if the constructor isn't doing anything fancy, I would trust LLVM to optimize those variables away in release builds. You can always profile and inline the expressions later if you find a bottleneck.

Aesthetically, consider using the field name as the name of the local variable, as others have said, to reduce redundancy in the struct constructor.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.