Why is it not possible to create HashSet<TcpStream>?

with Vec or HashMap it works fine, but not with HashSet?

use std::net::{TcpListener, TcpStream};
use std::collections::HashSet;

#[derive(PartialEq, Eq, Hash)]
struct Connection {
    name: String,
    stream: TcpStream,
}

impl Connection {
    fn new(name: String, stream: TcpStream) -> Connection {
        Connection { name, stream }
    }
}

fn main() {
    let mut connections = HashSet::new();
    let listener = TcpListener::bind("127.0.0.1:13370").unwrap();

    for stream in listener.incoming() {
        let stream = stream.unwrap();
        let name = String::from("John");
        connections.insert(Connection::new(name, stream));
    }
}

error[E0369]: binary operation == cannot be applied to type std::net::TcpStream

The trait Eq, Hash are not implemented for TcpStream

You cannot compare two streams, because two streams are never equal. For the same reason they cannot be hashed. What's wrong with putting it in a vec?

2 Likes

oh, thanks. I wanted to use HashSet to be sure it has no duplicates

Unless you're referring to duplicate names, then it's impossible to put a duplicate stream into a Vec, because in Rust you cannot just willy nilly make several of the same value. The stream is owned somewhere, and if you put it into the Vec, the Vec owns it. You cannot put it into the Vec if it's already owned by the Vec.

If you just don't want to have equal IP addresses, just create a HashMap with the key being equal to the Ip Address in String format

Of course, the same ip could open several connections. And there's no reason to convert to a string. The IpAddr type implements Hash and can be used as a key in a hashmap.

2 Likes

<continued-conversation-on-this-topic>
@yavl I hope that works for you then? :slight_smile: