How can I use `index_mut` to get a mutable reference? - rust

Even when I implement IndexMut for my struct, I cannot get a mutable reference to an element of structure inner vector.
use std::ops::{Index, IndexMut};
struct Test<T> {
data: Vec<T>,
}
impl<T> Index<usize> for Test<T> {
type Output = T;
fn index<'a>(&'a self, idx: usize) -> &'a T {
return &self.data[idx];
}
}
impl<T> IndexMut<usize> for Test<T> {
fn index_mut<'a>(&'a mut self, idx: usize) -> &'a mut T {
// even here I cannot get mutable reference to self.data[idx]
return self.data.index_mut(idx);
}
}
fn main() {
let mut a: Test<i32> = Test { data: Vec::new() };
a.data.push(1);
a.data.push(2);
a.data.push(3);
let mut b = a[1];
b = 10;
// will print `[1, 2, 3]` instead of [1, 10, 3]
println!("[{}, {}, {}]", a.data[0], a.data[1], a.data[2]);
}
How can I use index_mut to get a mutable reference? Is it possible?

You're almost there. Change this:
let mut b = a[1];
b = 10;
to this:
let b = &mut a[1];
*b = 10;
Indexing syntax returns the value itself, not a reference to it. Your code extracts one i32 from your vector and modifies the variable - naturally, it does not affect the vector itself. In order to obtain a reference through the index, you need to write it explicitly.
This is fairly natural: when you use indexing to access elements of a slice or an array, you get the values of the elements, not references to them, and in order to get a reference you need to write it explicitly.

Related

How can concatenated &[u8] slices implement the Read trait without additional copying?

The Read trait is implemented for &[u8]. How can I get a Read trait over several concatenated u8 slices without actually doing any concatenation first?
If I concatenate first, there will be two copies -- multiple arrays into a single array followed by copying from single array to destination via the Read trait. I would like to avoid the first copying.
I want a Read trait over &[&[u8]] that treats multiple slices as a single continuous slice.
fn foo<R: std::io::Read + Send>(data: R) {
// ...
}
let a: &[u8] = &[1, 2, 3, 4, 5];
let b: &[u8] = &[1, 2];
let c: &[&[u8]] = &[a, b];
foo(c); // <- this won't compile because `c` is not a slice of bytes.
You could use the multi_reader crate, which can concatenate any number of values that implement Read:
let a: &[u8] = &[1, 2, 3, 4, 5];
let b: &[u8] = &[1, 2];
let c: &[&[u8]] = &[a, b];
foo(multi_reader::MultiReader::new(c.iter().copied()));
If you don't want to depend on an external crate, you can wrap the slices in a struct of your own and implement Read for it:
struct MultiRead<'a> {
sources: &'a [&'a [u8]],
pos_in_current: usize,
}
impl<'a> MultiRead<'a> {
fn new(sources: &'a [&'a [u8]]) -> MultiRead<'a> {
MultiRead {
sources,
pos_in_current: 0,
}
}
}
impl Read for MultiRead<'_> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let current = loop {
if self.sources.is_empty() {
return Ok(0); // EOF
}
let current = self.sources[0];
if self.pos_in_current < current.len() {
break current;
}
self.pos_in_current = 0;
self.sources = &self.sources[1..];
};
let read_size = buf.len().min(current.len() - self.pos_in_current);
buf[..read_size].copy_from_slice(&current[self.pos_in_current..][..read_size]);
self.pos_in_current += read_size;
Ok(read_size)
}
}
Playground
Create a wrapper type around the slices and implement Read for it. Compared to user4815162342's answer, I delegate down to the implementation of Read for slices:
use std::{io::Read, mem};
struct Wrapper<'a, 'b>(&'a mut [&'b [u8]]);
impl<'a, 'b> Read for Wrapper<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let slices = mem::take(&mut self.0);
match slices {
[head, ..] => {
let n_bytes = head.read(buf)?;
if head.is_empty() {
// Advance the child slice
self.0 = &mut slices[1..];
} else {
// More to read, put back all the child slices
self.0 = slices;
}
Ok(n_bytes)
}
_ => Ok(0),
}
}
}
fn main() {
let parts: &mut [&[u8]] = &mut [b"hello ", b"world"];
let mut w = Wrapper(parts);
let mut buf = Vec::new();
w.read_to_end(&mut buf).unwrap();
assert_eq!(b"hello world", &*buf);
}
A more efficient implementation would implement further methods from Read, such as read_to_end or read_vectored.
See also:
How do I implement a trait I don't own for a type I don't own?

Mutable borrow into two parts with cleanup

I have some object that I want to split into two parts via a mutable borrow, then combine those back together into the original object when the split references go out of scope.
The simplified example below is for a Count struct that holds a single i32, which we want to split into two &mut i32s, who are both incorporated back into the original Count when the two mutable references go out of scope.
The approach I am taking below is to use an intermediate object CountSplit which holds a mutable reference to the original Count object and has the Drop trait implemented to do the re-combination logic.
This approach feels kludgy. In particular, this is awkward:
let mut ms = c.make_split();
let (x, y) = ms.split();
Doing this in one line like let (x, y) = c.make_split().split(); is not allowed because the intermediate object must have a longer lifetime. Ideally I would be able to do something like let (x, y) = c.magic_split(); and avoid exposing the intermediate object altogether.
Is there a way to do this which doesn't require doing two let's every time, or some other way to tackle this pattern that would be more idiomatic?
#[derive(Debug)]
struct Count {
val: i32,
}
trait MakeSplit<'a> {
type S: Split<'a>;
fn make_split(&'a mut self) -> Self::S;
}
impl<'a> MakeSplit<'a> for Count {
type S = CountSplit<'a>;
fn make_split(&mut self) -> CountSplit {
CountSplit {
top: self,
second: 0,
}
}
}
struct CountSplit<'a> {
top: &'a mut Count,
second: i32,
}
trait Split<'a> {
fn split(&'a mut self) -> (&'a mut i32, &'a mut i32);
}
impl<'a, 'b> Split<'a> for CountSplit<'b> {
fn split(&mut self) -> (&mut i32, &mut i32) {
(&mut self.top.val, &mut self.second)
}
}
impl<'a> Drop for CountSplit<'a> {
fn drop(&mut self) {
println!("custom drop occurs here");
self.top.val += self.second;
}
}
fn main() {
let mut c = Count { val: 2 };
println!("{:?}", c); // Count { val: 2 }
{
let mut ms = c.make_split();
let (x, y) = ms.split();
println!("split: {} {}", x, y); // split: 2 0
// each of these lines correctly gives a compile-time error
// c.make_split(); // can't borrow c as mutable
// println!("{:?}", c); // or immutable
// ms.split(); // also can't borrow ms
*x += 100;
*y += 5000;
println!("split: {} {}", x, y); // split: 102 5000
} // custom drop occurs here
println!("{:?}", c); // Count { val: 5102 }
}
playground:
I don't think a reference to a temporary value like yours can be made to work in today's Rust.
If it's any help, if you specifically want to call a function with two &mut i32 parameters like you mentioned in the comments, e.g.
fn foo(a: &mut i32, b: &mut i32) {
*a += 1;
*b += 2;
println!("split: {} {}", a, b);
}
you can already do that with the same number of lines as you'd have if your chaining worked.
With the chaining, you'd call
let (x, y) = c.make_split().split();
foo(x, y);
And if you just leave out the conversion to a tuple, it looks like this:
let mut ms = c.make_split();
foo(&mut ms.top.val, &mut ms.second);
You can make it a little prettier by e.g. storing the mutable reference to val directly in CountSplit as first, so that it becomes foo(&mut ms.first, &mut ms.second);. If you want it to feel even more like a tuple, I think you can use DerefMut to be able to write foo(&mut ms.0, &mut ms.1);.
Alternatively, you can of course formulate this as a function taking a function
impl Count {
fn as_split<F: FnMut(&mut i32, &mut i32)>(&mut self, mut f: F) {
let mut second = 0;
f(&mut self.val, &mut second);
self.val += second;
}
}
and then just call
c.as_split(foo);

How to implement Iterator yielding mutable references [duplicate]

This question already has an answer here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
Closed 1 year ago.
I am trying to implement a simple lookup iterator:
pub struct LookupIterMut<'a, D> {
data : &'a mut [D],
indices : &'a [usize],
i: usize
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.indices.len() {
None
} else {
let index = self.indices[self.i] as usize;
self.i += 1;
Some(&mut self.data[index]) // error here
}
}
}
The idea was to allow a caller consecutive mutable access to an internal storage. However I am getting the error cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements.
As far as I understand I would have to change the function signature to next(&'a mut self) -> .. but this would not be an Iterator anymore.
I also discovered that I could simply use raw pointers, though I am not sure if this is appropriate here:
// ...
type Item = *mut D;
// ...
Thanks for your help
Your code is invalid because you try to return multiple mutable references to the same slice with the same lifetime 'a.
For such a thing to work, you would need a different lifetime for each returned Item so that you wouldn't hold 2 mutable references to the same slice. You cannot do that for now because it requires Generic Associated Types:
type Item<'item> = &'item mut D; // Does not work today
One solution is to check that the indices are unique and to rebind the lifetime of the referenced item to 'a in an unsafe block. This is safe because all the indices are unique, so the user cannot hold 2 mutable references to the same item.
Don't forget to encapsulate the whole code inside a module, so that the struct cannot be build without the check in new:
mod my_mod {
pub struct LookupIterMut<'a, D> {
data: &'a mut [D],
indices: &'a [usize],
i: usize,
}
impl<'a, D> LookupIterMut<'a, D> {
pub fn new(data: &'a mut [D], indices: &'a [usize]) -> Result<Self, ()> {
let mut uniq = std::collections::HashSet::new();
let all_distinct = indices.iter().all(move |&x| uniq.insert(x));
if all_distinct {
Ok(LookupIterMut {
data,
indices,
i: 0,
})
} else {
Err(())
}
}
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
self.indices.get(self.i).map(|&index| {
self.i += 1;
unsafe { std::mem::transmute(&mut self.data[index]) }
})
}
}
}
Note that your code will panic if one index is out of bounds.
Using unsafe
Reminder: it is unsound to have, at any time, two accessible mutable references to the same underlying value.
The crux of the problem is that the language cannot guarantee that the code abides by the above rule, should indices contain any duplicate, then the iterator as implemented would allow obtaining concurrently two mutable references to the same item in the slice, which is unsound.
When the language cannot make the guarantee on its own, then you either need to find an alternative approach or you need to do your due diligence and then use unsafe.
In this case, on the Playground:
impl<'a, D> LookupIterMut<'a, D> {
pub fn new(data: &'a mut [D], indices: &'a [usize]) -> Self {
let set: HashSet<usize> = indices.iter().copied().collect();
assert!(indices.len() == set.len(), "Duplicate indices!");
Self { data, indices, i: 0 }
}
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.indices.len() {
None
} else {
let index = self.indices[self.i];
assert!(index < self.data.len());
self.i += 1;
// Safety:
// - index is guaranteed to be within bounds.
// - indices is guaranteed not to contain duplicates.
Some(unsafe { &mut *self.data.as_mut_ptr().offset(index as isize) })
}
}
}
Performance wise, the construction of a HashSet in the constructor is rather unsatisfying but cannot really be avoided in general. If indices was guaranteed to be sorted for example, then the check could be performed without allocation.

Accessing two vectors in a struct locked by a mutex [duplicate]

This question already has an answer here:
Error while trying to borrow 2 fields from a struct wrapped in RefCell
(1 answer)
Closed 3 years ago.
I have a struct with two vectors that is passed through a function while in a Arc<Mutex<TwoArrays>>.
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop A: compiles
for i in 0..f.a.len() {
for j in 0..f.b.len() {
f.b[j] += f.a[i];
}
}
//Loop B: does not compile
for i in f.a.iter() {
for j in 0..f.b.len() {
f.b[j] += i;
}
}
}
When I make a loop that uses an iterator, with another loop writing inside(Loop B), the compiler complains:
error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
Loop A Compiles.
Why is there a immutable borrow on f?
Can I make it only borrow each array individually? That is, a mutable borrow of f.b and a immutable borrow of f.a?
Why does this not happen when I pass TwoArrays directly? It only happens when I pass it in as an Arc<Mutex<TwoArrays>>
When you unwrap the LockResult you get a MutexGuard, and not directly a TwoArrays. You can use it as if it was a TwoArrays because it implements Deref and DerefMut.
When you try to write 2 loops, you try to use both deref and deref_mut at once: that's impossible:
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop B: does not compile
for i in f.a.iter() {
// ^~~~~~~~~~~~~~~~~~~ Implicit call to `deref` here.
for j in 0..f.b.len() {
// ^~~~~~~~~~~~ Another implicit call to `deref` here.
f.b[j] += i;
// ^~~~~~~~~~~~~~~~~~~~ Implicit call to `deref_mut` here.
}
}
}
If you deref_mut once before doing the loops, everything works fine:
use std::{sync::{Arc, Mutex}, ops::DerefMut};
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(foo: &mut Arc<Mutex<TwoArrays>>) {
let mut mutex_guard = foo.lock().unwrap();
let real_two_arrays = mutex_guard.deref_mut();
for i in &mut real_two_arrays.a {
for j in &real_two_arrays.b {
*i += *j;
}
}
}
You can access to two vector in a struct like following:
use std::mem;
#[derive(Debug)]
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: TwoArrays) {
let a = foo.a.clone();
let mut b = foo.b.clone();
for i in a.iter() {
let mut index = 0;
for _j in b.iter_mut() {
let mut new_value = i.clone() + foo.b[index as usize].clone();
mem::swap(&mut foo.b[index as usize], &mut new_value);
index = index + 1;
}
}
println!("Arrays A: {:?}", &foo.a);
println!("Arrays A: {:?}", &foo.b);
}
fn main() {
let a = vec![1i32, 2i32, 3i32];
let b = vec![4i32, 5i32, 6i32];
let two_arrays = TwoArrays { a, b };
// let foo = Arc::new(Mutex::new(two_arrays));
add_arrays(two_arrays);
}
Playground
Why is there an immutable borrow for f?
Because you tried to iterate it with iter() not the iter_mut()
And why does this not happen when I pass TwoArrays directly? It only happens when I pass it in as an Arc<Mutex<TwoArrays>>
You can pass it as naked struct without the need of Arc<Mutex<>> with the sample code.
If you insist on using Arc<Mutex<>> to pass the same object around with an atomic reference you can change the function signature to the following:
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>)
And you need to lock() and get that reference from the Arc with following:
let foo = foo.lock().unwrap();
Playground With Arc Usage

Is it possible to pass an object method as argument to a function and bind it to the object?

Is it possible to make a bind to object method? For example, I have a vector and a lot of functions which do something if some item exists in the vector. I would implement it as follows:
fn perform_if_exists(item: u8, vector: &Vec<u8>, func: fn(usize)) {
let idx = vector.iter().position(|i| *i == item );
match idx {
Some(i) => func(i),
None => {},
}
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
perform_if_exists(1, &v, Vec<_>::remove);
}
but it gives a lot of errors. I think they are reasonable but it's because I don't understand how to put vector's method as argument to a function.
Is it possible
Sure it is. You have to fix the multiple cascading errors first:
Invalid syntax: Vec<_>::remove isn't valid.
Incompatible argument types: Vec::remove modifies a Vec, so you have to pass in a Vec somehow.
Mutability: Vec::remove modifies a Vec, so you have to declare that the function is allowed to do so.
Vec::remove returns the removed value, so you have to allow the function to return a value, even if it's thrown away.
fn perform_if_exists<F, R>(item: u8, vector: &mut Vec<u8>, func: F)
where
F: Fn(&mut Vec<u8>, usize) -> R,
{
let idx = vector.iter().position(|i| *i == item);
if let Some(i) = idx {
func(vector, i);
}
}
fn main() {
let mut v = vec![1, 2, 3];
perform_if_exists(1, &mut v, Vec::remove);
println!("{:?}", v);
}
I switched to a generic as that's generally how you will accept closures. A function pointer is fine but more restrictive.
A method in Rust is nothing more than a function, which also takes a first self parameter. The method Vec::remove takes two arguments: &mut self and index: usize. The self parameter is always of type Self, which is Vec<u8> in this case. The complete type of Vec::<u8>::remove is: fn(&mut Vec<u8>, usize) -> u8 (yes it also returns the removed element).
After changing the type in your code (+ a few minor mistakes), it works:
// vvv-- has to be mutable
fn perform_if_exists(item: u8, vector: &mut Vec<u8>, func: fn(&mut Vec<u8>, usize) -> u8) {
let idx = vector.iter().position(|i| *i == item );
match idx {
Some(i) => {
func(vector, i);
},
None => {},
}
}
fn main() {
let mut v: Vec<u8> = vec![1, 2, 3];
perform_if_exists(1, &mut v, Vec::remove);
}
But fn(...) -> ... types are raw pointer types and just work for ordinary functions. Often you also want to enable the user to pass anything that is "callable", like closures. There are traits exactly for that purpose: Fn(...) -> ....
Let me propose another solution:
fn perform_if_exists<T, F, R>(item: T, vector: &mut Vec<T>, func: F) -> Option<R>
where F: FnOnce(&mut Vec<T>, usize) -> R,
T: PartialEq
{
let idx = vector.iter().position(|i| *i == item );
idx.map(|i| func(vector, i))
}
This solution is far more generic as it allows arbitrary item types, arbitrary "callable" types and returns the value that is returned by the given function. Note that the main function didn't change; the solution is more generic, but all old uses still work.

Resources