As I can make the vector is mutable inside struct - rust

As I can make the vector is mutable
pub struct Test<'a>{
vec: &'a mut Vec<i32>,
}
impl<'a> Test<'a> {
pub fn created()->Test<'a>{
Test {vec: &'a mut Vec::new() }
}
pub fn add(&self, value: i32){
self.vec.push(value);
}
}
expected `:`, found `mut`
Test {vec: &'a mut Vec::new() }
^~~
This is a similar question but
and the answer works, but what if I do not want, you can do this, "applying the response link"
pub struct Test{
vec: Vec<i32>,
}
impl Test {
pub fn created()->Test {
Test {vec: Vec::new() }
}
pub fn add(&mut self, value: i32){
self.vec.push(value);
}
}
..//
let mut test: my::Test = my::Test::created();
test.add(1i32);
let mut test1: my::Test = my::Test::created();
test1 = test; <-- I do not want, you can do this
..//
as I can make the vector is mutable, without making it be all the struct

Maybe you are looking for interior mutability. Please, do not use interior mutability loosely, read this first.
use std::cell::RefCell;
pub struct Test{
vec: RefCell<Vec<i32>>,
}
impl Test {
pub fn created()->Test {
Test {vec: RefCell::new(Vec::new()) }
}
pub fn add(&self, value: i32){
self.vec.borrow_mut().push(value);
}
}
fn main() {
let test = Test::created();
test.add(1i32);
let test1 = Test::created();
// test1 = test; // does not work anymore
}

Related

Rust Help Needed: Issue with "cannot borrow data in a `&` reference as mutable" [duplicate]

This question already has answers here:
How do I create a global, mutable singleton?
(7 answers)
Closed 3 months ago.
I am new to rust and cannot understand the issue below. I am trying to store the Trait of Animals in the vector.
My implementation is as below.
mod TestAnimal {
use crate::stack;
pub trait Animal {
fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
}
pub struct Hospital {
animals: Vec<Box<dyn Animal>>,
}
static mut HOSPITAL: Hospital = Hospital { animals: Vec::new() };
impl Hospital {
pub fn add_animal(&mut self, animal: Box<dyn Animal>) {
self.animals.push(animal);
}
}
pub fn get_hospital() -> &'static Hospital {
unsafe {
return &HOSPITAL;
}
}
}
#[test]
fn test_hospital() {
pub struct Cat;
impl TestAnimal::Animal for Cat {
fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
return Ok(());
}
}
TestAnimal::get_hospital().add_animal(Box::new(Cat {}));
}
The issue I am facing is as below.
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:45:5
|
45 | TestAnimal::get_hospital().add_animal(Box::new(Cat {}));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
Looks like you are trying to mutate a static variable. Normally this isn't safe because multiple threads editing a value at the same time can cause issues. You can make it safe by wrapping the variable in a mutex. A mutex will ensure that only one thread can mutate the variable at a time.
mod test_animal {
use crate::stack;
use std::sync::Mutex;
pub trait Animal { 0 implementations
fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
}
pub struct Hospital { 1 implementation
animals: Vec<Box<dyn Animal + Send>>,
}
pub static HOSPITAL: Mutex<Hospital> = Mutex::new(Hospital {
animals: Vec::new(),
});
impl Hospital {
pub fn add_animal(&mut self, animal: Box<dyn Animal + Send>) {
self.animals.push(animal);
}
}
}
#[test]
fn test_hospital() {
pub struct Cat;
impl test_animal::Animal for Cat {
fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
return Ok(());
}
}
test_animal::HOSPITAL
.lock()
.unwrap()
.add_animal(Box::new(Cat {}));
}
That said, sometimes you'll find you don't actually need a static variable. Mutable static variables often make code harder to understand. You might consider doing this instead:
mod test_animal {
use crate::stack;
pub trait Animal {
fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
}
pub struct Hospital {
animals: Vec<Box<dyn Animal + Send>>,
}
impl Hospital {
pub fn new() -> Self {
Self {
animals: Vec::new(),
}
}
pub fn add_animal(&mut self, animal: Box<dyn Animal + Send>) {
self.animals.push(animal);
}
}
}
#[test]
fn test_hospital() {
pub struct Cat;
impl test_animal::Animal for Cat {
fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
return Ok(());
}
}
let mut hospital = test_animal::Hospital::new();
hospital.add_animal(Box::new(Cat {}));
}

Returning a mutable reference to a value behind Arc and Mutex

pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> &mut Vec<TreeLine> {
???????????????????????????????
}
}
I need help writing the get_the_forest function. I've tried many various things but they all return compilation errors. I need to return a mutable reference to Vec<TreeLine> which is wrapped behind an Arc and a Mutex in self.m_tree_lines.
There is no way of doing this.
You create a concrete MutexGuard object that releases the mutex when it dropped when you call lock; you cannot move a reference out of the scope that contains the guard:
pub fn as_mut(&mut self) -> &Whatever {
let mut guard = self.data.lock().unwrap();
Ok(guard.deref())
drop(guard) // <--- implicitly added here, which would invalidate the ref
}
You also cannot return both the mutex guard and a reference, for more complex reasons (basically rust cannot express that), for the same reason it cannot have a reference and an object in a single structure; see the discussion on Why can't I store a value and a reference to that value in the same struct?
...so basically your best bet is one of two things:
/// Return the mutex guard itself
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
/// Pass a function in, which patches the mutable internal value
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard); // <-- patch happens while guard is still alive
Ok(())
}
Full code:
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::PoisonError;
use std::error::Error;
use std::fmt;
use std::fmt::Formatter;
use std::ops::Deref;
#[derive(Debug, Copy, Clone)]
pub enum TreeLockError {
FailedToLock
}
impl Error for TreeLockError {}
impl fmt::Display for TreeLockError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl<T> From<PoisonError<T>> for TreeLockError {
fn from(_: PoisonError<T>) -> Self {
TreeLockError::FailedToLock
}
}
// ---
#[derive(Debug)]
pub struct TreeLine {
pub value: &'static str
}
pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard);
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
let mut vm = ForesterViewModel::new();
{
let mut trees = vm.get_the_forest()?;
trees.push(TreeLine{ value: "one"});
trees.push(TreeLine{ value: "two"});
} // <--- Drop the mutable reference here so you can get it again later
// Patch
vm.patch_forest(|trees| {
trees.push(TreeLine{ value: "three"});
});
// ...
let trees = vm.get_the_forest()?;
println!("{:?}", trees.deref());
Ok(())
}

Creation of a hashmap with struct in Rust

I am trying to set up a hashmap of objects / structs in rust... But I don't understand this concrete problem (a lifetime error).
#[derive(Hash, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Node<'a> {
identifier: &'a str,
sha_id: Vec<u8>,
successor_id: Option<Vec<u8>>,
predecessor_id: Option<Vec<u8>>,
}
impl<'a> Node<'a> {
...
..
.
}
pub struct Application<'a> {
hash_map: HashMap<&'a str, Node>,
}
impl<'a> Application<'a> {
fn join(&self, node: &Node) {
self.hash_map.insert(node.identifier, node);
}
}
The error is a missing lifetime specifier in the hash_map: HashMap<&'a str, Node> that I tried to solve changing Node to Node<'a> but It throws a "mismatched type" error when I try to insert...
I don't exactly why I have this problem missing the lifetime and I don't find solutions..
UPDATE:
#[derive(Hash, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Node<'a> {
identifier: &'a str,
sha_id: Vec<u8>,
successor_id: Option<Vec<u8>>,
predecessor_id: Option<Vec<u8>>,
}
impl<'a> Node<'a> {
...
..
.
}
pub struct Application<'a> {
hash_map: HashMap<&'a str, Node<'a>>,
}
impl<'a> Application<'a> {
fn join(&self, node: &Node) {
self.hash_map.insert(node.identifier, *node);
}
}
And the output is:
"explicit lifetime required in the type of `node`"
UPDATE2:
pub struct Application<'a> {
hash_map: HashMap<&'a str, Node<'a>>,
}
impl<'a> Application<'a> {
fn join(&mut self, node: &'a Node<'a>) {
self.hash_map.insert(node.identifier, *node);
}
}
And the output is:
self.hash_map.insert(node.identifier, *node); cannot move out of borrowed content
COMPLETE SOLUTION
#[derive(Clone, Hash, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Node<'a> {
identifier: &'a str,
sha_id: Vec<u8>,
successor_id: Option<Vec<u8>>,
predecessor_id: Option<Vec<u8>>,
}
impl<'a> Node<'a> {
...
..
.
}
pub struct Application<'a> {
hash_map: HashMap<&'a str, Node<'a>>,
}
impl<'a> Application<'a> {
fn join(&mut self, node: Node<'a>) {
self.hash_map.insert(node.identifier, node);
}
}
This simplified example seems to work:
use std::collections::HashMap;
#[derive(Clone)] // we'll be cloning it later on
struct Node<'a> {
data: &'a i32
}
struct Test<'a> {
hash_map: HashMap<&'a str, Node<'a>> // the hash map owns the struct
}
impl<'a> Test<'a> {
fn new() -> Test<'a> {
Test {hash_map: HashMap::new()}
}
fn join(
&mut self, // must be mutable
node: Node<'a>) { // do not pass a reference
self.hash_map.insert("test", node); // inserting moves `node`
}
}
fn main() {
let stuff = Node {data: &12};
let mut test = Test::new();
test.join(stuff.clone()); // if we don't clone, `stuff` will get moved
println!("{}", *test.hash_map["test"].data); // outputs "12"
}
Since std::collections::HashMap::insert attempts to move its second argument, one can't dereference a pointer to something and pass that to this method because otherwise the pointer will become uninitialized, which isn't permitted. A way so solve this is to pass a moved value and not a pointer to join.
For poor idiots like myself, who are trying to find out how to put hashmaps in a struct, no need to spend many hours "playing" with lifetimes(the 'a in the above example). They are not required in the slightest, just use String instead of &str in your structure.
struct ComputerConfig {
hostname: String,
// displays: Vec<DispConfig>,
}
struct MyConfig {
pub config_version: u8,
computers: HashMap<String, ComputerConfig>, // the hash map owns the struct
}
impl MyConfig {
fn new() -> MyConfig {
MyConfig {
computers: HashMap::new(),
config_version: 1,
}
}
/// Join is used to add a new ComputerConfig into the hashmap
fn join(
&mut self, // must be mutable
key: &str,
node: ComputerConfig,
) {
// do not pass a reference
self.computers.insert(key.to_string(), node); // inserting moves `node`
}
}
fn main() {
let mut cfg = MyConfig::new()
cfg.join("test", stuff);
println!("{:?}", &cfg); // outputs "12"
}

How to return a reference to a sub-value of a value that is under a mutex?

I have a structure that looks somewhat like this:
pub struct MyStruct {
data: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
I can easily get a lock on the mutex and query the underlying HashMap:
let d = s.data.lock().unwrap();
let v = d.get(&1).unwrap();
println!("{:?}", v);
Now I want to make a method to encapsulate the querying, so I write something like this:
impl MyStruct {
pub fn get_data_for(&self, i: &i32) -> &Vec<i32> {
let d = self.data.lock().unwrap();
d.get(i).unwrap()
}
}
This fails to compile because I'm trying to return a reference to the data under a Mutex:
error: `d` does not live long enough
--> <anon>:30:9
|
30 | d.get(i).unwrap()
| ^
|
note: reference must be valid for the anonymous lifetime #1 defined on the block at 28:53...
--> <anon>:28:54
|
28 | pub fn get_data_for(&self, i: &i32) -> &Vec<i32> {
| ^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 29:42
--> <anon>:29:43
|
29 | let d = self.data.lock().unwrap();
| ^
I can fix it by wrapping the HashMap values in an Arc, but it looks ugly (Arc in Arc) and complicates the code:
pub struct MyStruct {
data: Arc<Mutex<HashMap<i32, Arc<Vec<i32>>>>>,
}
What is the best way to approach this? Is it possible to make a method that does what I want, without modifying the data structure?
Full example code.
The parking_lot crate provides an implementation of Mutexes that's better on many accounts than the one in std. Among the goodies is MutexGuard::map, which implements an interface similar to owning_ref's.
use std::sync::Arc;
use parking_lot::{Mutex, MutexGuard, MappedMutexGuard};
use std::collections::HashMap;
pub struct MyStruct {
data: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
impl MyStruct {
pub fn get_data_for(&self, i: &i32) -> MappedMutexGuard<Vec<i32>> {
MutexGuard::map(self.data.lock(), |d| d.get_mut(i).unwrap())
}
}
You can try it on the playground here.
This solution is similar to #Neikos's, but using owning_ref to do hold the MutexGuard and a reference to the Vec:
extern crate owning_ref;
use std::sync::Arc;
use std::sync::{Mutex,MutexGuard};
use std::collections::HashMap;
use std::vec::Vec;
use owning_ref::MutexGuardRef;
type HM = HashMap<i32, Vec<i32>>;
pub struct MyStruct {
data: Arc<Mutex<HM>>,
}
impl MyStruct {
pub fn new() -> MyStruct {
let mut hm = HashMap::new();
hm.insert(3, vec![2,3,5,7]);
MyStruct{
data: Arc::new(Mutex::new(hm)),
}
}
pub fn get_data_for<'ret, 'me:'ret, 'c>(&'me self, i: &'c i32) -> MutexGuardRef<'ret, HM, Vec<i32>> {
MutexGuardRef::new(self.data.lock().unwrap())
.map(|mg| mg.get(i).unwrap())
}
}
fn main() {
let s: MyStruct = MyStruct::new();
let vref = s.get_data_for(&3);
for x in vref.iter() {
println!("{}", x);
}
}
This has the advantage that it's easy (through the map method on owning_ref) to get a similar reference to anything else reachable from the Mutex (an individual item in a Vec, etc.) without having to re-implement the returned type.
This can be made possible by using a secondary struct that implements Deref and holds the MutexGuard.
Example:
use std::sync::{Arc, Mutex, MutexGuard};
use std::collections::HashMap;
use std::ops::Deref;
pub struct Inner<'a>(MutexGuard<'a, HashMap<i32, Vec<i32>>>, i32);
impl<'a> Deref for Inner<'a> {
type Target = Vec<i32>;
fn deref(&self) -> &Self::Target {
self.0.get(&self.1).unwrap()
}
}
pub struct MyStruct {
data: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
impl MyStruct {
pub fn get_data_for<'a>(&'a self, i: i32) -> Inner<'a> {
let d = self.data.lock().unwrap();
Inner(d, i)
}
}
fn main() {
let mut hm = HashMap::new();
hm.insert(1, vec![1,2,3]);
let s = MyStruct {
data: Arc::new(Mutex::new(hm))
};
{
let v = s.get_data_for(1);
println!("{:?}", *v);
let x : Vec<_> = v.iter().map(|x| x * 2).collect();
println!("{:?}", x); // Just an example to see that it works
}
}
As described in Why can't I store a value and a reference to that value in the same struct?, the Rental crate allows for self-referential structs in certain cases. Here, we bundle the Arc, the MutexGuard, and the value all into a struct that Derefs to the value:
#[macro_use]
extern crate rental;
use std::{
collections::HashMap, sync::{Arc, Mutex},
};
use owning_mutex_guard_value::OwningMutexGuardValue;
pub struct MyStruct {
data: Arc<Mutex<HashMap<i32, Vec<i32>>>>,
}
impl MyStruct {
pub fn get_data_for(&self, i: &i32) -> OwningMutexGuardValue<HashMap<i32, Vec<i32>>, Vec<i32>> {
OwningMutexGuardValue::new(
self.data.clone(),
|d| Box::new(d.lock().unwrap()),
|g, _| g.get(i).unwrap(),
)
}
}
rental! {
mod owning_mutex_guard_value {
use std::sync::{Arc, Mutex, MutexGuard};
#[rental(deref_suffix)]
pub struct OwningMutexGuardValue<T, U>
where
T: 'static,
U: 'static,
{
lock: Arc<Mutex<T>>,
guard: Box<MutexGuard<'lock, T>>,
value: &'guard U,
}
}
}
fn main() {
let mut data = HashMap::new();
data.insert(1, vec![1, 2, 3]);
let s = MyStruct {
data: Arc::new(Mutex::new(data)),
};
let locked_data = s.get_data_for(&1);
let total: i32 = locked_data.iter().map(|x| x * 2).sum();
println!("{}", total);
assert!(s.data.try_lock().is_err());
drop(locked_data);
assert!(s.data.try_lock().is_ok());
}
Here's an implementation of the closure-passing approach mentioned in the comments:
impl MyStruct {
pub fn with_data_for<T>(&self, i: &i32, f: impl FnOnce(&Vec<i32>) -> T) -> Option<T> {
let map_guard = &self.data.lock().ok()?;
let vec = &map_guard.get(i)?;
Some(f(vec))
}
}
Rust Playground
Example usage:
s.with_data_for(&1, |v| {
println!("{:?}", v);
});
let sum: i32 = s.with_data_for(&1, |v| v.iter().sum()).unwrap();
println!("{}", sum);

Construct a Vector of any Type with a Trait Constraint

I'd like to have a struct, with a member that is a Vec with a Trait Constraint on the types in the Vector. Right now, this is what I am trying:
pub trait SomeTrait {
fn some_function(&self);
}
pub struct SomeStruct<T: SomeTrait> {
member: Vec<T>
}
impl<T: SomeTrait> SomeStruct<T> {
pub fn new() -> SomeStruct<T> {
SomeStruct {
member: Vec::new()
}
}
}
fn main() {
let mut some_struct = SomeStruct::new();
}
And the compiler is giving me:
error: the trait 'sometrait::SomeTrait' is not implemented for the type '_'
let mut some_struct = SomeStruct::new();
^~~~~~~~~~~
note: required by 'somestruct::SomeStruct<T>::new'
let mut some_struct = SomeStruct::new();
^~~~~~~~~~~
I've tried placing <T: SomeTrait> in various places throughout, but just getting even stranger compiler errors, so those attempts must be way off base.
Thanks in advance for any help!
The problem is that you haven't given the compiler enough information to figure out what T is. That's what the _ is for: it's having to infer the parameter to SomeStruct.
Also, there are no types anywhere in this example that implement SomeTrait. If you fix both of these problems, it works (with some warnings):
pub trait SomeTrait {
fn some_function(&self);
}
pub struct SomeStruct<T: SomeTrait> {
member: Vec<T>
}
impl<T: SomeTrait> SomeStruct<T> {
pub fn new() -> SomeStruct<T> {
SomeStruct {
member: Vec::new()
}
}
}
impl SomeTrait for i32 {
fn some_function(&self) {}
}
fn main() {
let mut some_struct_a: SomeStruct<i32> = SomeStruct::new();
let mut some_struct_b = SomeStruct::<i32>::new();
}

Resources