1

Using the following code:

use std::{
    io::{BufRead, BufReader},
    net::TcpListener,
};

fn inicializar(receptor: TcpListener) {
    let mut peticion: Vec<&str> = Vec::new();
    let mut respuesta = String::new();
    let mut lector_buffer;

    for recibido in receptor.incoming() {
        let recibido = recibido.expect("Unable to accept");
        lector_buffer = BufReader::new(recibido);
        lector_buffer
            .read_line(&mut respuesta)
            .expect("could not read");
        peticion = respuesta.split_whitespace().collect();

        println!("quote es {}", peticion[0]);
    }
}

Yields this error:

error[E0502]: cannot borrow `respuesta` as mutable because it is also borrowed as immutable
  --> src/lib.rs:12:24
   |
12 |             .read_line(&mut respuesta)
   |                        ^^^^^^^^^^^^^^ mutable borrow occurs here
13 |             .expect("could not read");
14 |         peticion = respuesta.split_whitespace().collect();
   |         --------   --------- immutable borrow occurs here
   |         |
   |         immutable borrow might be used here, when `peticion` is dropped and runs the `Drop` code for type `std::vec::Vec`

How can I make it work?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366

1 Answers1

2

In the loop you're filling a buffer, which you share between connections. And at each connection you're splitting it again.

You want to split only for the current connection:

fn inicializar(receptor: TcpListener) {
    for recibido in receptor.incoming() {
        let recibido = recibido.expect("Unable to accept");
        let mut lector_buffer = BufReader::new(recibido);
        let mut respuesta = String::new();
        lector_buffer
            .read_line(&mut respuesta)
            .expect("could not read");
        let peticion: Vec<&str> = respuesta.split_whitespace().collect();
        println!("quote es {}", peticion[0]);
    }
}

If you want to keep the string outside the loop, you probably want to use instances of String rather than just &str (because they're pointers and they have to point to something which is kept).

This can be something like

fn inicializar(receptor: TcpListener) {
    let mut peticions: Vec<Vec<String>> = Vec::new();
    for recibido in receptor.incoming() {
        let recibido = recibido.expect("Unable to accept");
        let mut lector_buffer = BufReader::new(recibido);
        let mut respuesta = String::new();
        lector_buffer
            .read_line(&mut respuesta)
            .expect("could not read");
        let peticion: Vec<String> = respuesta
            .split_whitespace()
            .map(|s| s.to_string())
            .collect();
        println!("quote es {}", peticion[0]);
        peticions.push(peticion);
    }
    // you can use peticions here, or even return it
}

At this point you need to structure your program by defining structs to avoid dealing with Vecs of Vecs.

trent
  • 25,033
  • 7
  • 51
  • 90
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 2
    The OP may have wanted to declare `respuesta` outside of the loop to re-use the buffer without reallocating, in which case it would be fine to do so but needs a `respuesta.clear()` at the end of the loop. See [Weird behaviour when using read_line in a loop](https://stackoverflow.com/questions/45232943/weird-behaviour-when-using-read-line-in-a-loop) – trent Oct 29 '19 at 15:04