0

For this project, I'm using the ssh2 crate. From my Cargo.toml:

[dependencies]
clap = "~2.33.3"
ssh2 = "0.8"

I have this struct:

pub struct AFile {
    full_path: String,                  //Fullpath of file
    initialized: bool,                  //true when struct is initialized
    status: u8,                         //custom status
    fp: Option<File>,                   //file pointer
    size: u64,                          //size in bytes
    protocol: u8,                       //protocol to work with
    session: Option<Session>,           //session for some protocols
    ssh_channel: Option<ssh2::Channel>, //channel for ssh
}

And initialized it:

pub fn new(ifp: String, i_protocol: u8) -> Self {
    Self {
        full_path: ifp,
        initialized: true,
        status: STATUS_UNDEFINED,
        fp: None,
        size: 0,
        protocol: i_protocol,
        session: None,
        ssh_channel: None,
    }
}

Everything works fine when I implement reading and writing local files. Adding SSH support I'm facing a problem in the reading function:

fn read_bytes(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
    match self.protocol {
        0 => match self.fp.as_ref().unwrap().read(buf) {
            Ok(u) => return Ok(u),
            Err(e) => return Err(e),
        },
        1 => match self.ssh_channel.as_ref().unwrap().read(buf) {
            Ok(u) => return Ok(u),
            Err(e) => return Err(e),
        },
        _ => return Ok(0),
    }; //end of match protocol
}

It does not compile:

error[E0596]: cannot borrow data in a `&` reference as mutable

       --> src\acopy.rs:168:28
        |
    168 |                 1 => match self.ssh_channel.as_ref().unwrap().read(buf) {
        |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

Why does this line work:

0 => match self.fp.as_ref().unwrap().read(buf) {

And this does not:

1 => match self.ssh_channel.as_ref().unwrap().read(buf) {

As far as I can understand, both read functions have the same parameters. From the Read docs I can see the declaration:

fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

From the File docs I can see the same:

fn read(&mut self, buf: &mut [u8]) -> Result<usize>

Am I messing up with borrowing?

Why does it work with File but not with ssh2::Channel?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user_0
  • 3,173
  • 20
  • 33
  • 1
    It's because `Read` is implemented for `&File` as well as `File`. [Why can I call File.take() on a reference?](https://stackoverflow.com/questions/31503429/why-can-i-call-file-take-on-a-reference) – trent Sep 29 '20 at 16:09
  • 1
    Your `match` can be [greatly simplified](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b824b2fa9ff7b65a7e9a28a1214d81ae) – Shepmaster Sep 29 '20 at 16:25
  • 1
    You probably want `as_mut` instead of `as_ref`. See also [How do I borrow a reference to what is inside an Option?](https://stackoverflow.com/a/22283089/155423); [Cannot move out of value which is behind a shared reference when unwrapping](https://stackoverflow.com/q/32338659/155423). – Shepmaster Sep 29 '20 at 16:26
  • Thank you all. Changed to as_mut and compile and works fine. I'm also going to semplify the match. – user_0 Sep 29 '20 at 16:43

0 Answers0