1

I want to write some code for my project. How can I dereference an Option<Arc<T>> correctly?

I have tried:

use std::io::Read;
use std::sync::Arc;

struct Map<T: Read> {
    shared_reader: Option<Arc<T>>,
}

impl<T: Read> Default for Map<T> {
    fn default() -> Self {
        Self {
            shared_reader: None,
        }
    }
}

impl<T: Read> Map<T> {
    fn read_raw_data(&mut self) -> Option<Vec<u8>> {
        if let Some(srd) = &mut self.shared_reader {
            /*I think the srd should have a type &mut Arc<T>*/
            let mut buf = Vec::with_capacity(4096);
            if let Ok(_) = srd.read_to_end(&mut buf) {
                return Some(buf);
            } else {
                return None;
            }
        } else {
            return None;
        }
    }
}

When I compile this, I get an error:

error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/lib.rs:21:28
   |
21 |             if let Ok(_) = srd.read_to_end(&mut buf) {
   |                            ^^^ cannot borrow as mutable

There is the solution

use std::borrow::BorrowMut;
use std::io::Read;
use std::sync::{Arc, Mutex};

struct Map<T: Read> {
    shared_reader: Option<Arc<Mutex<T>>>,
}

impl<T: Read> Default for Map<T> {
    fn default() -> Self {
        Self {
            shared_reader: None,
        }
    }
}

impl<T: Read> Map<T> {
    fn read_raw_data(&mut self) -> Option<Vec<u8>> {
        if let Some(srd_lock) = &self.shared_reader {
            if let Ok(srd) = &mut srd_lock.lock() {
                let mut buf = Vec::with_capacity(4096);
                if let Ok(_) = srd.read_to_end(&mut buf) {
                    return Some(buf);
                } else {
                    return None;
                }
            } else {
                return None;
            }
        } else {
            return None;
        }
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
skypitcher
  • 109
  • 7
  • Are you sure you need an `Option>`, rather than an `Arc – Peter Hall Jul 23 '19 at 10:13
  • The data in a `Arc` can only be accessed via an immutable reference. You need to wrap the contents in a `Mutex` (or something similar) if you want to mutate it (which you do, since `read_to_end` takes `&mut self`). – Joe Clay Jul 23 '19 at 10:20
  • It's great that you have a solution to your question! You should post it as an answer rather than an edit to your question and then potentially accept that answer. That way, the question shows up as solved in search results, people can vote on your answer, and your solution can be more helpful to future people with the same problem. – Shepmaster Jul 23 '19 at 14:21

0 Answers0