1
votes

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?

1

1 Answers

2
votes

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.