use std::rc::Rc; use std::cell::RefCell; #[derive(Debug)] struct Gadget { id: i32, // RefCell allows mutable borrows of `last_seen_at` even when Gadget is immutable last_seen_at: RefCell, } fn update_gadget_status(gadget: &Gadget, new_status: &str) { // We have an immutable reference `&Gadget`, // but `RefCell` allows us to mutably borrow its inner value. let mut status_ref = gadget.last_seen_at.borrow_mut(); *status_ref = new_status.to_string(); println!("Updated gadget {}: {}", gadget.id, *status_ref); // RefCell enforces borrowing rules at runtime. // Attempting to borrow_mut() again while `status_ref` is active would panic. // let forbidden_ref = gadget.last_seen_at.borrow_mut(); // This would panic! } fn main() { let my_gadget = Gadget { id: 1, last_seen_at: RefCell::new("2023-01-01".to_string()), }; println!("Initial gadget: {:#?}", my_gadget); update_gadget_status(&my_gadget, "2023-10-26 10:00"); println!("After update: {:#?}", my_gadget); // Using Rc> for shared mutable state in a single thread. let shared_gadget = Rc::new(RefCell::new(my_gadget)); let another_ref = Rc::clone(&shared_gadget); // Both `shared_gadget` and `another_ref` point to the same RefCell. // We can get mutable access through either of them. shared_gadget.borrow_mut().id = 2; another_ref.borrow_mut().last_seen_at.borrow_mut().push_str(" (via another ref)"); println!("Shared gadget final state: {:#?}", shared_gadget); println!("Another ref final state: {:#?}", another_ref); }