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 structstd::net::TcpStream
, but its trait bounds were not satisfied method cannot be called onstd::net::TcpStream
due to unsatisfied trait bounds note: the following trait bounds were not satisfied:std::net::TcpStream: futures::AsyncRead
which is required bystd::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 onstd::net::TcpStream
due to unsatisfied trait bounds tcp.rs(49, 1): doesn't satisfystd::net::TcpStream: futures::AsyncReadExt
tcp.rs(49, 1): doesn't satisfystd::net::TcpStream: futures::AsyncRead
mod.rs(580, 8): the method is available forstd::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...".
read
might be a method onRead
(if using a sync tcp stream from the standard library) or onAsyncRead
(viaAsyncReadExt
). 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