Rust - Suddenly Can't find split method on WebSocket? - rust

I'm a rust newbie and I'm having a lot of trouble getting some simple ws examples to run.
I have a new project with this in the Cargo.toml file:
[package]
name = "ouranos4"
version = "0.1.0"
authors = ["jasongoodwin <jay.michael.goodwin#gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1", features = ["full"] }
warp = "0.3"
And then I have the warp ws example found here: https://github.com/seanmonstar/warp/blob/master/examples/websockets.rs
// use futures::{FutureExt, StreamExt};
use warp::Filter;
#[tokio::main]
async fn main() {
let routes = warp::path("echo")
// The `ws()` filter will prepare the Websocket handshake.
.and(warp::ws())
.map(|ws: warp::ws::Ws| {
// And then our closure will be called when it completes...
ws.on_upgrade(|websocket| {
// Just echo all messages back...
let (tx, rx) = websocket.split();
rx.forward(tx).map(|result| {
if let Err(e) = result {
eprintln!("websocket error: {:?}", e);
}
})
})
});
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
And I swear this was compiling but out of the blue I'm getting these errors:
Compiling ouranos4 v0.1.0 (/Users/jasongoodwin/Development/src/ouranos4)
error[E0599]: no method named `split` found for struct `WebSocket` in the current scope
--> src/main.rs:13:42
|
13 | let (tx, rx) = websocket.split();
| ^^^^^ method not found in `WebSocket`
|
::: /Users/jasongoodwin/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.14/src/stream/stream/mod.rs:1359:8
|
1359 | fn split<Item>(self) -> (SplitSink<Self, Item>, SplitStream<Self>)
| ----- the method is available for `Box<WebSocket>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
2 | use futures_util::stream::stream::StreamExt;
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
error: could not compile `ouranos4`
I've recreated the project, cleaned the project, done everything imaginable. Switched the rust compiler version to nightly and back.
I'm really confused as to why I can't split this now. I've tried different examples, different crates, and I keep seeing this error.
I'm tempted to throw my laptop away and try on a different computer :P

I needed to add some more imports!
Thanks to kmdreko.
use futures::StreamExt;
use futures::FutureExt;

Related

oneshot::channel `tokio::sync::oneshot::Receiver<()>` is not an iterator add `use futures_util::FutureExt`

In the tokio tests I see they use oneshot::channel together with serve_with_shutdown but the the compiler tells me to add use futures_util::future::future::FutureExt but as you can see in the example below I already added that trait to the scope.
What am I missing?
Here a reprex
run cargo new tokio-test
Cargo.toml
[package]
name = "tokio-test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tonic = "0.7"
prost = "0.10.1"
tokio = { version = "1.18", features = ["macros", "rt-multi-thread"] }
[build-dependencies]
tonic-build = "0.7.2"
src/main.rs
pub mod console {
tonic::include_proto!("console");
}
use console::console_server::{Console, ConsoleServer};
use console::{ConsoleResponse, InfoRequest};
use tokio::runtime::Runtime;
use tokio::sync::oneshot;
use tonic::{transport::Server, Request, Response};
use futures_util::FutureExt;
#[derive(Default)]
pub struct ConsoleImpl {}
#[tonic::async_trait]
impl Console for ConsoleImpl {
async fn info(
&self,
request: Request<InfoRequest>,
) -> Result<Response<ConsoleResponse>, tonic::Status> {
println!("{}", request.get_ref().text);
Ok(Response::new(ConsoleResponse {}))
}
}
fn main() {
let addr = "[::1]:50051".parse().unwrap();
let maxconsole = ConsoleImpl::default();
println!("Console server listening on {}", addr);
let mut rt = Runtime::new().expect("failed to obtain a new RunTime object");
let (shutdown_send, shutdown_recv) = oneshot::channel::<()>();
let server_future = Server::builder()
.add_service(ConsoleServer::new(maxconsole))
// .serve(addr)
.serve_with_incoming_shutdown(
addr,
shutdown_recv.map(drop),
);
rt.block_on(server_future).expect("failed to successfully run the future on RunTime");
}
src/console.proto
syntax = "proto3";
package console;
service Console {
rpc info (InfoRequest) returns (ConsoleResponse) {}
}
message InfoRequest {
string text = 1;
}
message ConsoleResponse {
}
If you build the project it will complain
❯ cargo build
Updating crates.io index
Compiling tokio-test v0.1.0 (C:\s\tokio-test)
error[E0432]: unresolved import `futures_util`
--> src\main.rs:10:5
|
10 | use futures_util::FutureExt;
| ^^^^^^^^^^^^ use of undeclared crate or module `futures_util`
error[E0599]: `tokio::sync::oneshot::Receiver<()>` is not an iterator
--> src\main.rs:40:27
|
40 | shutdown_recv.map(drop),
| ^^^ `tokio::sync::oneshot::Receiver<()>` is not an iterator
|
::: C:\Users\FrancescElies\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-1.20.1\src\sync\oneshot.rs:318:1
|
318 | pub struct Receiver<T> {
| ---------------------- doesn't satisfy `tokio::sync::oneshot::Receiver<()>: Iterator`
|
= note: the following trait bounds were not satisfied:
`tokio::sync::oneshot::Receiver<()>: Iterator`
which is required by `&mut tokio::sync::oneshot::Receiver<()>: Iterator`
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use futures_util::future::future::FutureExt;
|
Some errors have detailed explanations: E0432, E0599.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `tokio-test` due to 2 previous errors
Yes, you added the FutureExt import, but did not tell Rust where to find that crate. The critical part of the error message is:
error[E0432]: unresolved import `futures_util`
--> src\main.rs:10:5
|
10 | use futures_util::FutureExt;
| ^^^^^^^^^^^^ use of undeclared crate or module `futures_util`
This can be fixed by adding the futures_util crate to your Cargo.toml dependency section.

Unresolved import for certain tokio features

I am trying to use tokios background event loop feature, but I am unable to use any tokio reactor features and I have no idea why. I created a new project with cargo new tokio-test --bin and copy-pasted the code snippet and in the link for establishing a basic TCP connection.
Cargo.toml
[package]
name = "tokio-test"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.11.0", features = ["full"] }
main.rs
use tokio::prelude::*;
use tokio::net::TcpStream;
fn main() {
let addr = "93.184.216.34:9243".parse().unwrap();
let connect_future = TcpStream::connect(&addr);
let task = connect_future
.and_then(|socket| {
println!("successfully connected");
Ok(())
})
.map_err(|e| println!("failed to connect; err={:?}", e));
tokio::run(task);
}
When running cargo build I get:
error[E0432]: unresolved import `tokio::prelude`
--> src/main.rs:1:12
|
1 | use tokio::prelude::*;
| ^^^^^^^ could not find `prelude` in `tokio`
error[E0425]: cannot find function `run` in crate `tokio`
--> src/main.rs:16:12
|
16 | tokio::run(task);
| ^^^ not found in `tokio`
error[E0599]: no method named `and_then` found for opaque type `impl Future` in the current scope
--> src/main.rs:10:10
|
10 | .and_then(|socket| {
| ^^^^^^^^ method not found in `impl Future`
|
help: consider `await`ing on the `Future` and calling the method on its `Output`
|
10 | .await.and_then(|socket| {
| ^^^^^^
Clearly I am missing some directive from tokio but I cannot figure how to include it. My rustc version is rustc 1.55.0 (c8dfcfe04 2021-09-06).
You're depending on tokio v1.11.0 (the current release), but your docs are for v0.1.22. The interface has changed quite drastically, that's why you are not finding all those types, functions and modules. Current documentation is here.
If you found the documentation via Google: The problem of Google returning old docs.rs results is well known. There is an open issue that will solve this problem.
Also, docs.rs displays a warning on the top left of the page to go to the latest version if you are not on that version anyway. You should get in the habit of clicking it unless you know you're using an older version. (Thanks to kmdreko for pointing this out in the comments)

MQTT connection with tokio

I'm trying to create an MQTT connection with tokio and the codec provided in the mqtt_v5 crate. My code does not compile, and I don't understand why. Here is what I have written so far, the send code might not be correct.
use tokio::net::TcpStream;
use tokio_util::codec::Framed;
use tokio_util::codec::Decoder;
use std::net::SocketAddrV4;
use mqtt_v5::types::Packet as MqttPacket;
use mqtt_v5::codec::MqttCodec;
use futures_sink::Sink;
use futures_core::stream::Stream;
struct MqttConn {
inner: Framed<TcpStream, MqttCodec>,
}
impl MqttConn {
async fn new(addr: SocketAddrV4) -> MqttConn {
let tcp = TcpStream::connect(addr).await.expect("cannot connect to mqtt");
MqttConn { inner: MqttCodec::new().framed(tcp) }
}
async fn handle(&self, handler: &dyn Fn(&MqttConn, MqttPacket) -> ()) {
while let Some(p) = self.inner.next().await {
handler(self, p)
}
}
async fn send(&self, p: MqttPacket) {
self.inner.start_send(p);
}
}
I get these errors from the compiler:
error[E0599]: no method named `framed` found for struct `MqttCodec` in the current scope
--> src/mqtt.rs:17:44
|
17 | MqttConn { inner: MqttCodec::new().framed(tcp) }
| ^^^^^^ method not found in `MqttCodec`
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope; perhaps add a `use` for it:
`use tokio_util::codec::decoder::Decoder;`
error[E0599]: no method named `next` found for struct `Framed<tokio::net::TcpStream, MqttCodec>` in the current scope
--> src/mqtt.rs:21:40
|
21 | while let Some(p) = self.inner.next().await {
| ^^^^ method not found in `Framed<tokio::net::TcpStream, MqttCodec>`
error[E0599]: no method named `start_send` found for struct `Framed<tokio::net::TcpStream, MqttCodec>` in the current scope
--> src/mqtt.rs:27:20
|
27 | self.inner.start_send(p);
| ^^^^^^^^^^ method not found in `Framed<tokio::net::TcpStream, MqttCodec>`
warning: unused import: `tokio_util::codec::Decoder`
--> src/mqtt.rs:3:5
|
3 | use tokio_util::codec::Decoder;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `futures_sink::Sink`
--> src/mqtt.rs:7:5
|
7 | use futures_sink::Sink;
| ^^^^^^^^^^^^^^^^^^
The compiler says that the Decoder trait is not in scope, but I use it. If I try the suggested import I find that the module tokio_util::codec::decoder is private. Based on the source tokio_util::codec::decoder::Decoder is reexported as tokio_util::codec::Decoder. Also if I read the docs correctly, Framed should implement Sink and Stream therefore it should have the next and start_send methods.
Relevant lines from Cargo.toml:
[dependencies]
tokio = { version = "1.0.1", features = ["full"] }
tokio-util = { version = "0.6", features = ["full"] }
futures-sink = "0.3.9"
futures-core = "0.3.9"
mqtt-v5 = "0.1.1"
How can I get this to compile?
You have a number of library incompatibilities that are causing some less-than-obvious error messages.
mqtt-v5 depends on tokio-util^0.3, which was written for tokio 0.2, not 1.0. You'll need to roll back to tokio 0.2 and tokio-util 0.3. This should fix the problem with Decoder and Sink.
Additionally, the Stream trait only provides poll_next(), which is the task-level stream method. next() is provided by the StreamExt trait, along with other convenience methods similar to those found in Iterator.

Why is 'futures::prelude::*; undecleared

For some reason it is telling me that it is undeclared when i am trying to follow an example for an IRC in rust and it makes no sense that it is not working cause i have used libraries like this before and it worked before so idk what is happening \
code:
use futures::prelude::*;
use irc::client::prelude::*;
#[tokio::main]
async fn main() -> irc::error::Result<()> {
let config = Config {
nickname: Some("pickles".to_owned()),
server: Some("chat.freenode.net".to_owned()),
channels: vec!["#rust-spam".to_owned()],
..Default::default()
};
let mut client = Client::from_config(config).await?;
client.identify()?;
let mut stream = client.stream()?;
let sender = client.sender();
while let Some(message) = stream.next().await.transpose()? {
print!("{}", message);
match message.command {
Command::PRIVMSG(ref target, ref msg) => {
if msg.contains(client.current_nickname()) {
sender.send_privmsg(target, "Hi!")?;
}
}
_ => (),
}
}
Ok(())
}
Errors
--> src\main.rs:1:5
|
1 | use futures::prelude::*;
| ^^^^^^^ use of undeclared type or module `futures`
error[E0308]: mismatched types
--> src\main.rs:9:19
|
9 | channels: vec!["#rust-spam".to_owned()],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::option::Option`, found struct `std::vec::Vec`
| help: try using a variant of the expected enum: `Some(<[_]>::into_vec(box [$($x),+]))`
|
= note: expected enum `std::option::Option<std::vec::Vec<_>>`
found struct `std::vec::Vec<_>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no function or associated item named `from_config` found for trait object `dyn irc::client::Client` in the current scope
--> src\main.rs:13:30
|
13 | let mut client = Client::from_config(config).await?;
| ^^^^^^^^^^^ function or associated item not found in `dyn irc::client::Client`
Cargo.toml
[package]
name = "irc"
version = "0.1.0"
authors = ["sudo"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
irc = "0.13"
tokio = { version = "0.2.22", features = ["full"] }
Edit: Added Cargo.toml
You will need to add the futures crate to your cargo file. E.g. from the docs
[dependencies]
futures = "0.3"
You need to add futures to your Cargo.toml, even though a dependency already depends on it.

Rust actix_web::main "expected `std::result::Result<(), std::io::Error>` because of return type" but suggested type doesen't work

I'm new to rust and started experimenting with actix_web and sqlx. the goal is to create a simple, open-source Blog engine, but after I implemented the CLI argument parser and basic SQL connection pool, the code doesn't compile anymore. I'm getting the following error:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::io::Result<()> {
| ------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
the error suggests to use std::result::Result<(), std::io::Error> as return type, but I get the same error when replacing the current return type with it:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::result::Result<(), std::io::Error> {
| --------------------------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
so far I couldn't find anybody with the same issue and could not find any reason for it.
My Code:
/Cargo.toml
[package]
name = "rusty_read"
version = "0.1.0"
authors = ["LeMoonStar <webmaster#unitcore.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "3.0.0-beta.1"
rust-ini = "0.15"
sqlx = { version = "0.4.0-beta.1", features = [ "all-databases", "any", "tls" ] }
clap = "2"
/src/main.rs
use actix_web::{get, web, App, HttpServer, Responder};
use ini::Ini;
use sqlx::pool::Pool;
use sqlx::any;
#[get("/")]
async fn index() -> impl Responder {
format!("index")
}
#[get("/article/{id}")]
async fn article(info: web::Path<u32>) -> impl Responder {
format!("article nr.{}", info)
}
#[actix_web::main]
async fn main() -> std::result::Result<(), std::io::Error> {
let conf = Ini::load_from_file("conf.ini").unwrap_or(Ini::load_from_str("[Server]
bindAddress = \"127.0.0.1:8080\"
[Database]
url = \"mysql://user:password#localhost/blog\"
").unwrap());
let matches = clap::App::new("Rusty Read")
.version("0.1 INDEV")
.author("LeMoonStar <webmaster#unitcore.de>")
.about("a blog engine written in rust")
.subcommand(clap::SubCommand::with_name("config")
.about("sets various configurations for the blog")
.arg(clap::Arg::with_name("address")
.short("a")
.long("adress")
.help("sets the address the http server binds on (eg. 127.0.0.1:8080)")
.takes_value(true))
.arg(clap::Arg::with_name("database")
.short("d")
.long("database")
.help("sets the url to the database (eg. mysql://user:password#localhost/blog)")
.takes_value(true)))
.subcommand(clap::SubCommand::with_name("init_database")
.about("Initializes the database which is set in the conf.ini file (or with the config command)"))
.get_matches();
if let Some(matches) = matches.subcommand_matches("config") {
if matches.is_present("address") {
conf.section(Some("Server")).unwrap()
.insert("bindAddress", "127.0.0.1:8080");
}
if matches.is_present("database") {
conf.section(Some("Database")).unwrap()
.insert("url", "mysql://user:password#localhost/blog");
}
} else if let Some(matches) = matches.subcommand_matches("init_database") {
} else {
let mut section = conf.section(Some("Server")).expect("conf.ini requires a [Server] section.");
let bind_address = section.get("bindAddress").expect("conf.ini's [Server] section requires a bindAdress.");
section = conf.section(Some("Database")).expect("conf.ini requires a [Database] section.");
let db_url = section.get("url").expect("conf.ini's [Database] section requires a url.");
let pool = Pool::<any::Any>::connect(db_url).await.expect("database connection pool could not be created.");
HttpServer::new(move || {
App::new()
.service(article)
.service(index)
.data(pool.clone())
})
.bind(bind_address).expect("could not bind http server")
.run()
.await;
}
}
I hope someone can help me with this problem since I can't continue to work on the project, while this problem is present.
the Ok(()) is actually working.. I've tried to copy-pasting all of your code before, and do cargo check i got the same problem as you write there on the comment. then I tried to clean the code inside the main function and then copy-pasting your code again piece by piece. after adding Ok(()) as the return of the main. and the error changed before I even finished the copy-pasting. see
the screenshot of different error on my local.
then I tried to fix it by adding clone() like below:
..
conf.section(Some("Server")).unwrap().clone()
..
conf.section(Some("Database")).unwrap().clone()
..
and then I cargo run it. and the server works fine! see the screenshot here.

Resources