Reputation: 17384
How can I convert an Option
of one type into an Option
of another type in Rust?
I managed to sketch this out in the Rust playground, but this is a lot of boilerplate code to do what seems like a common operation.
In this example, I have a data transfer object which contains an Option::<String>
, which I wish to convert to an Option::<Price>
type, where Price
is some internal struct type.
#[derive(Debug)]
struct DTO {
pub dto_data: Option::<String>,
}
#[derive(Debug)]
struct Price {
pub internal_price: i64,
}
#[derive(Debug)]
struct InternalType {
pub internal_data: Option::<Price>,
}
fn main() {
let dto = DTO {
dto_data: Some(String::from("10")),
};
println!("{:?}", dto);
let mut option_price: Option<Price> = None;
if let Some(price_exists) = dto.dto_data {
option_price = Some(Price {
internal_price: price_exists.parse().unwrap()
});
}
let internal_type = InternalType {
internal_data: option_price,
};
println!("{:?}", internal_type);
}
Actually, I am fairly sure there is a bug in my code, because the Rust playground produces warnings about dead code. Still, the output seems ok.
That point aside, does Rust provide a simpler way to do this? Perhaps with some kind of helper function or trait?
Compiling playground v0.0.1 (/playground)
warning: field `internal_price` is never read
--> src/main.rs:9:9
|
8 | struct Price {
| ----- field in this struct
9 | pub internal_price: i64,
| ^^^^^^^^^^^^^^
|
= note: `Price` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
warning: field `internal_data` is never read
--> src/main.rs:14:9
|
13 | struct InternalType {
| ------------ field in this struct
14 | pub internal_data: Option::<Price>,
| ^^^^^^^^^^^^^
|
= note: `InternalType` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
warning: `playground` (bin "playground") generated 2 warnings
Finished dev [unoptimized + debuginfo] target(s) in 0.80s
Running `target/debug/playground`
DTO { dto_data: Some("10") }
InternalType { internal_data: Some(Price { internal_price: 10 }) }
Upvotes: 0
Views: 943
Reputation: 22818
You are probably asking for Option::map
:
#[derive(Debug)]
struct DTO {
pub dto_data: Option<String>,
}
#[derive(Debug)]
struct Price {
pub internal_price: i64,
}
#[derive(Debug)]
struct InternalType {
pub internal_data: Option<Price>,
}
fn main() {
let dto = DTO {
dto_data: Some(String::from("10")),
};
println!("{:?}", dto);
let internal_type = InternalType {
internal_data: dto.dto_data.map(|p| Price {
internal_price: p.parse().unwrap(),
}),
};
println!("{:?}", internal_type);
}
DTO { dto_data: Some("10") }
InternalType { internal_data: Some(Price { internal_price: 10 }) }
Upvotes: 4