0
votes

SOLUTION: I needed to add "use std::io::prelude::*;" to my code. I do not know why.

I am trying to read from an std::net::TcpStream but I recieve this error when calling stream.read(&buf).unwrap;

the method read exists for struct std::net::TcpStream, but its trait bounds were not satisfied method cannot be called on std::net::TcpStream due to unsatisfied trait bounds note: the following trait bounds were not satisfied: std::net::TcpStream: futures::AsyncRead which is required by std::net::TcpStream: futures::AsyncReadExt help: items from traits can only be used if the trait is in scoperustc(E0599) main.rs(31, 16): method cannot be called on std::net::TcpStream due to unsatisfied trait bounds tcp.rs(49, 1): doesn't satisfy std::net::TcpStream: futures::AsyncReadExt tcp.rs(49, 1): doesn't satisfy std::net::TcpStream: futures::AsyncRead mod.rs(580, 8): the method is available for std::boxed::Box<std::net::TcpStream> here

Code:

use irc::client::prelude::*;
use futures::prelude::*;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
use std::io;
use futures::{AsyncRead, AsyncReadExt};

const NAME: &str = "nickname";

#[derive(Debug)]
struct DCC {
    ip: IpAddr,
    port: u16,
}

impl DCC {
    fn from_msg(msg: &str) -> Result<DCC, std::num::ParseIntError> {
        let msg_split: Vec<&str> = msg.split_whitespace().collect();
        let ip: u32 = msg_split[3].parse()?;
        let ip_addr: IpAddr = IpAddr::V4(Ipv4Addr::from(ip));
        let port_num: u16 = msg_split[4].parse()?;
        let dcc = DCC{
           ip: ip_addr,
           port: port_num,
        };
        return Ok(dcc);
    }
    async fn connect(&self) -> Result<(), io::Error>{
        let socket_addr = SocketAddr::new(self.ip, self.port);
        let mut socket = TcpStream::connect(socket_addr)?;
        let mut buf = vec![];
        socket.read(&buf).unwrap();
        return Err(io::Error::new(io::ErrorKind::Other, "oh no!"));
    }
}

#[tokio::main]
async fn irc_get(name: &str) -> Result<String, irc::error::Error>{
    let config = Config {
        nickname: Some(NAME.to_owned()),
        server: Some("irc.irchighway.net".to_owned()),
        port: Some(6667),
        use_tls: Some(false),
        channels: vec!["#ebooks".to_owned()],
        ..Config::default()
    };
    let mut client = Client::from_config(config).await?;
    client.identify()?;

    
    let mut stream = client.stream()?;

    //waits for server to log us in and then sends the search request
    loop{ 
        let m = match stream.next().await{
            Some(v) => v,
            None => panic!("at the disco")
        };
        let message = match &m {
                 Ok(message) => match &message.command {Command::NOTICE(_s1, s2)=> {print!("{:?} \n", s2); message}, _ => message},
                Err(_e) => panic!("at the disco")};
        match &message.command{
            Command::NOTICE(_s, msg) => { if msg.contains("Welcome to #ebooks"){break}}, 
            _=> ()    
        }          
    }
    client.send_privmsg("#ebooks", format!["@Search {}", name])?;
    loop{
        let m = match stream.next().await.transpose()?{
            Some(m) => m,
            None => panic!("at the disco")
        };
        match &m.command{
            Command::PRIVMSG(nm, msg) => if nm == NAME {println!("{:?}",m); return Ok(String::from(msg))},
            _ => ()
        }
    }
}


fn main() {
    let dcc = DCC::from_msg(&irc_get(&"romeo and juliet").unwrap()[..]);
    println!("{:?}", dcc);
}

I'm fairly new at rust and based on all of the examples in the documentation I think I'm using .read correctly. My only thought is that maybe it's because I'm trying to write the code in the impl, but I don't know if rust treats that differently. It also fails with "async fn connect..." and with "fn connect...".

1
It's hard to know what you're doing without a minimal reproduction example, and at the very east the entire error message*. But you seem to be mixing synchronous and asynchronous APIs which doesn't help. One very relevant thing in Rust is that trait methods require the trait to be in scope. read might be a method on Read (if using a sync tcp stream from the standard library) or on AsyncRead (via AsyncReadExt). The corresponding trait(s) need to be imported explicitely (possibly via a "prelude import" but I dislike that in long-term cases) in order for the method to be accessible.Masklinn
Edited question with full error message and all my code (including the new import statement suggested in the answer below (which did not fix the error)).aghayes
This is also not my first rust project, I already built a complet web application backend with user login and postgressql. So while I am new, I am at least familiar with rust and I have read just under half of the rustbook so far.aghayes

1 Answers

0
votes

The compiler was telling you the solution:

help: items from traits can only be used if the trait is in scope

You need to import the traits in order to use them:

use futures::{AsyncRead, AsyncReadExt};

Also you would probably want to use tokio::TcpStream which is async and not the std one.