I've got these structs:
#[derive(Debug, RustcDecodable)]
struct Config {
ssl: Option<SslConfig>,
}
#[derive(Debug, RustcDecodable)]
struct SslConfig {
key: Option<String>,
cert: Option<String>,
}
They get filled from a toml
file. This works perfectly fine. Since I got an Option<T>
in it I either have to call unwrap()
or do a match
.
But if I want to do the following:
let cfg: Config = read_config(); // Reads a File, parses it and returns the Config-Struct
let keypath = cfg.ssl.unwrap().key.unwrap();
let certpath = cfg.ssl.unwrap().cert.unwrap();
It won't work because cfg.ssl
gets moved to keypath
. But why does it get moved? I call unwrap()
on ssl
to get the key (and unwrap()
it to). So the result of key.unwrap()
should get moved?
Or am I missing a point? Whats the best way to make these structs accessible like this (or in a other neat way)? I tried to implement #[derive(Debug, RustcDecodable, Copy, Clone)]
but this won't work because I have to implement Copy
to String
as well. Then I have to implement Copy
to Vec<u8>
and so on. There must be a more convenient solution?
We can access Nested Structure in C in the following two ways: Using Normal variable. Using Pointer variable.
What is the definition of Option::unwrap
? From the documentation:
fn unwrap(self) -> T
it consumes its input (cfg.ssl
here).
This is not what you want, you instead want to go from Option<T>
to &T
, which will start by consuming &self
(by reference, not value)... or you want to clone
the Option
before calling unwrap
.
Cloning is rarely the solution... the alternative here is as_ref
:
fn as_ref(&self) -> Option<&T>
And therefore you can write:
let keypath /*: &String*/ = cfg.ssl.as_ref().unwrap().key.as_ref().unwrap();
^~~~~~~ ^~~~~~~~
So the result of
key.unwrap()
should get moved?
Yes, but not only that. The key insight here is, that a variable get's moved into of unwrap()
. Let's look at the function signature:
fn unwrap(self) -> T { ... }
It takes self
, so the object is moved into the function. But this applies to ssl.unwrap()
, too!
So when writing:
cfg.ssl.unwrap().key.unwrap();
You first move cfg.ssl
into unwrap()
, then you access one field of the result and move that field into unwrap()
again. So yes, cfg.ssl
is moved. In order to solve this, you can save the temporary result of the first unwrap()
call, like so:
let ssl = cfg.ssl.unwrap();
let keypath = ssl.key.unwrap();
let certpath = ssl.cert.unwrap();
Or you can look at the as_ref()
method, if you don't want to move (which is probably the case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With