struct MyResource { id: u32, data: String, } impl Drop for MyResource { fn drop(&mut self) { println!("Dropping MyResource with ID: {}", self.id); } } struct ResourceContainer { resource: Option, } impl ResourceContainer { fn new(id: u32, data: &str) -> Self { ResourceContainer { resource: Some(MyResource { id, data: data.to_string() }), } } // Safely takes ownership of the resource, leaving `None` in its place. // This prevents double-frees or use-after-move scenarios. fn take_resource(&mut self) -> Option { self.resource.take() } // Shows current state without moving the resource fn inspect_resource(&self) { match &self.resource { Some(r) => println!("Container holds resource ID: {}", r.id), None => println!("Container holds no resource."), } } } fn main() { let mut container = ResourceContainer::new(1, "Initial data"); container.inspect_resource(); // Take the resource from the container if let Some(resource_taken) = container.take_resource() { println!("Successfully took resource with ID: {}", resource_taken.id); // resource_taken is now owned here, and will be dropped when it goes out of scope. // container.resource is now None. } else { println!("Failed to take resource."); } container.inspect_resource(); // Attempting to take again will yield None if let Some(resource_taken_again) = container.take_resource() { println!("This should not happen: took resource again with ID: {}", resource_taken_again.id); } else { println!("Cannot take resource again, it's already gone."); } // When `container` goes out of scope, it will drop its `resource` field, // which is currently `None`, so no double-drop occurs. }