I have a big object that I need boxed in another object but I don't necessarily need it all the time. So I want to use an if statement to get the optional boxed TempStructure but i'm not exactly sure how I can destructure and dereference at the same time.
Example:
pub struct TempStructure {
lots_of_data: [u64; 64],
}
pub struct Structure {
pending_removal: Option<Box<(TempStructure, bool)>>,
}
impl Structure {
pub fn do_somthing(&mut self) {
// How do I destructure the Option and dereference the Box to get TempStructure?
if let Some((temp_structure, some_boolean)) = self.pending_removal.take() {
// Do something with temp_structure and some_boolean
}
}
}
When I do this ^^^ I get an expected struct `std::boxed::Box`, found tuple
error.
Destructuring is the process of breaking down items into their component parts, binding each to smaller variables.
Rust provides pattern matching via the match keyword, which can be used like a C switch . The first matching arm is evaluated and all possible values must be covered.
Patterns are a special syntax in Rust for matching against the structure of types, both complex and simple. Using patterns in conjunction with match expressions and other constructs gives you more control over a program's control flow.
Instead of matching on an element, call the method in the trait on it. TLDR: in Rust, to match over type, we create a trait, implement a function for each type and call it on the element to match. Surround it with backticks to mark it as code. Single backticks for inline code, triple backticks for code blocks.
Dereference the box after matching:
if let Some(inner) = self.pending_removal.take() {
let (temp_structure, some_boolean) = *inner;
// Do something with temp_structure and some_boolean
}
(playground)
If you think this is a bit clunky, you're right. On nightly you can use the unstable box_patterns
feature to enable a better syntax for this (although this might never be stabilized):
if let Some(box (temp_structure, some_boolean)) = self.pending_removal.take() {
// Do something with temp_structure and some_boolean
}
(playground)
You can fix this with adding a .as_deref()
after the take()
:
pub struct TempStructure {
lots_of_data: [u64; 64],
}
pub struct Structure {
pending_removal: Option<Box<(TempStructure, bool)>>,
}
impl Structure {
pub fn do_somthing(&mut self) {
// How do I destructure the Option and dereference the Box to get TempStructure?
if let Some((temp_structure, some_boolean)) = self.pending_removal.take().as_deref() {
// Do something with temp_structure and some_boolean
}
}
}
Box<T>
dereferences to &T
, as_deref()
dereferences the value of the Option
, therefore it gives you a &T
out of your Option<Box<T>>
.
Edit: another option is to dereference the Box to move the value out of it:
if let Some((temp_structure, some_boolean)) = self.pending_removal.take().map(|boxed| *boxed) {
// assignments just for demonstration purposes that we now get
// owned values rather than references.
let _: TempStructure = temp_structure;
let _: bool = some_boolean;
}
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