How to chain tokio read functions? - asynchronous

Is there a way to chain the read_* functions in tokio::io in a "recursive" way ?
I'm essentially looking to do something like:
read_until x then read_exact y then write response then go back to the top.
In case you are confused what functions i'm talking about: https://docs.rs/tokio/0.1.11/tokio/io/index.html

Yes, there is a way.
read_until is returns a struct ReadUntil, which implements the Future-trait, which iteself provides a lot of useful functions, e.g. and_then which can be used to chain futures.
A simple (and silly) example looks like this:
extern crate futures;
extern crate tokio_io; // 0.1.8 // 0.1.24
use futures::future::Future;
use std::io::Cursor;
use tokio_io::io::{read_exact, read_until};
fn main() {
let cursor = Cursor::new(b"abcdef\ngh");
let mut buf = vec![0u8; 2];
println!(
"{:?}",
String::from_utf8_lossy(
read_until(cursor, b'\n', vec![])
.and_then(|r| read_exact(r.0, &mut buf))
.wait()
.unwrap()
.1
)
);
}
Here I use a Cursor, which happens to implement the AsyncRead-trait and use the read_until function to read until a newline occurs (between 'f' and 'g').
Afterwards to chain those I use and_then to use read_exact in case of an success, use wait to get the Result unwrap it (don't do this in production kids!) and take the second argument from the tuple (the first one is the cursor).
Last I convert the Vec into a String to display "gh" with println!.

Related

How to write type definition with tokio_serde::SymmetricallyFramed::new()?

I am rying to serialize cbor using serde_tokio.
I can make a simple program work, but I need to actually store the tokio_serde::SymmetricallyFramed::new() in a structure to use it more than once.
(It consumes the socket, which is cool).
I can't seem to write a type that will store the value.
use futures::prelude::*;
use tokio::net::TcpStream;
use tokio_serde::formats::*;
use tokio_util::codec::{FramedWrite, LengthDelimitedCodec};
#[tokio::main]
pub async fn main() {
// Bind a server socket
let socket = TcpStream::connect("127.0.0.1:17653").await.unwrap();
// Delimit frames using a length header
let length_delimited = FramedWrite::new(socket, LengthDelimitedCodec::new());
// Serialize frames with JSON
let mut serialized = tokio_serde::SymmetricallyFramed::new(length_delimited, SymmetricalCbor::default());
// Send the value
serialized
.send(vec![1i32,2,3])
.await
.unwrap()
}
produces the right output. (Adopted from the json example in tokio-serde crate, here: https://github.com/carllerche/tokio-serde/blob/master/examples/client.rs
I want to put "serialized" into a structure (and hide how it is created in a fn), but I can't seem to write the right type.
use futures::prelude::*;
use serde_cbor;
use tokio::net::TcpStream;
use tokio_serde::formats::*;
use tokio_util::codec::{FramedWrite, LengthDelimitedCodec};
type CborWriter = tokio_serde::Framed<tokio_util::codec::FramedWrite<tokio::net::TcpStream, tokio_util::codec::LengthDelimitedCodec>, serde_cbor::Value, serde_cbor::Value, tokio_serde::formats::Cbor<serde_cbor::Value, serde_cbor::Value>>;
// something like this has been suggested, but so far no luck.
// fn setup_writer(socket: tokio::net::TcpStream) -> impl Sink<??>+Debug {
fn setup_writer(socket: tokio::net::TcpStream) -> CborWriter {
// Delimit frames using a length header
let length_delimited = FramedWrite::new(socket, LengthDelimitedCodec::new());
// Serialize frames with CBOR
let serialized = tokio_serde::SymmetricallyFramed::new(length_delimited, SymmetricalCbor::default());
return serialized;
}
#[tokio::main]
pub async fn main() {
// Bind a server socket
let socket = TcpStream::connect("127.0.0.1:17653").await.unwrap();
// Serialize frames with CBOR
let mut serialized = setup_writer(socket);
// Send the value
serialized
.send(serde_cbor::Value::Array(vec![serde_cbor::Value::Integer(1i128),
serde_cbor::Value::Integer(2i128),
serde_cbor::Value::Integer(3i128)]))
.await
.unwrap()
}
But, I don't want to put cbor::Value in. I should just be able to put the Serializable objects in. So I am obviously going in the wrong direction here. The JSON example in the tokio-serde crate is happy to put in/out serde_json::Value, but I should have to do that, I think.
A suggestion on Discord was made to change the first example as:
let mut serialized: () = tokio_serde::SymmetricallyFramed::new(length_delimited, SymmetricalCbor::default());
and let the compiler tell me what the type is:
= note: expected unit type `()`
found struct `tokio_serde::Framed<tokio_util::codec::FramedWrite<tokio::net::TcpStream, tokio_util::codec::LengthDelimitedCodec>, _, _, tokio_serde::formats::Cbor<_, _>>`
Well, I can't put _ into the type alias, or write it directly.
I think it should say something like "impl Serialize", but that's not yet a thing.
Obviously, the compiler gets the first example right, so there must be something that will go in there... but what?

Iterate over the sorted elements in a collection in tuples

I am trying to iterate over the sorted elements in a collection in tuples of 2 or more.
If I had a Vec, I could call
for window in my_vec.windows(2) {
// do something with window
}
but Vecs aren't implicitly sorted, which would be really nice to have. I tried to use a BTreeSet instead of a Vec, but I don't seem to be able to call windows on it.
When trying to call
for window in tree_set.iter().windows(2) {
// do something with window
}
I get the error
no method named `windows` found for type `std::collections::btree_set::Iter<'_, Card>` in the current scope
Itertools provides the tuple_windows method:
extern crate itertools;
use itertools::Itertools;
use std::collections::BTreeSet;
fn main() {
let items: BTreeSet<_> = vec![1, 3, 2].into_iter().collect();
for (a, b) in items.iter().tuple_windows() {
println!("{} < {}", a, b);
}
}
Note that windows is a method on slices, not on iterators, and it returns an iterator of subslices of the original slice. A BTreeMap presumably cannot provide that same iterator interface because it isn't built on top of a contiguous hunk of data; there's going to be some value that isn't immediately next in memory to the subsequent value.

Cannot compare &u8 with u8

fn count_spaces(text: Vec<u8>) -> usize {
text.split(|c| c == 32u8).count()
}
The above function does not compile, and gives the following error on the comparison:
trait `&u8: std::cmp::PartialEq` not satisfied
I read this as: "c is a borrowed byte and cannot be compared to a regular byte", but I must be reading this wrong.
What would be the appropriate way to split a Vec<u8> on specific values?
I do realize that there are options when reading files, like splitting a BufReader or I could convert the vector to a string and use str::split. I might go with such a solution (passing in a BufReader instead of a Vec<u8>), but right now I'm just playing around, testing stuff and want to know what I'm doing wrong.
The code
You are actually reading it right: c is indeed a borrowed byte and cannot be compared to a regular byte. Try using any of the functions below instead:
fn count_spaces(text: Vec<u8>) -> usize {
text.split(|&c| c == 32u8).count()
}
fn count_spaces(text: Vec<u8>) -> usize {
text.split(|c| *c == 32u8).count()
}
The first one uses pattern matching on the parameter (&c) to dereference it, while the second one uses the dereference operator (*).
Why is c a &u8 instead of a u8?
If you take a look at the split method on the docs, you will see that the closure parameter is a borrow of the data in Vec. In this case, it means that the parameter will be &u8 instead of u8 (so in your code you are actually comparing &u8 to u8, which Rust doesn't like).
In order to understand why the closure takes the parameter by borrow and not by value, consider what would happen if the parameter was taken by value. In the case of Vec<u8>, there would be no problem since u8 implements Copy. However, in the case of a a Vec<String>, each String would be moved into the closure and destroyed!

Function with same name as struct

In general, I prefer to write initializer functions with descriptive names. However, for some structs, there is an obvious default initializer function. The standard Rust name for such a function is new, placed in the impl block for the struct. However, today I realized that I can give a function the same name as a struct, and thought this would be a good way to implement the obvious initializer function. For example:
#[derive(Debug, Clone, Copy)]
struct Pair<T, U> {
first: T,
second: U,
}
#[allow(non_snake_case)]
fn Pair<T, U>(first: T, second: U) -> Pair<T, U> {
Pair::<T, U> {
first: first,
second: second,
}
}
fn main(){
let x = Pair(1, 2);
println!("{:?}", x);
}
This is, in my opinion, much more appealing than this:
let x = Pair::new(1, 2);
However, I've never seen anyone else do this, and my question is simply if there are any problems with this approach. Are there, for example, ambiguities which it can cause which will not be there with the new implementation?
If you want to use Pair(T, U) then you should consider using a tuple struct instead:
#[derive(Debug, Clone, Copy)]
struct Pair<T, U>(T, U);
fn main(){
let x = Pair(1, 2);
println!("{:?}", x);
println!("{:?}, {:?}", (x.0, x.1));
}
Or, y’know, just a tuple ((T, U)). But I presume that Pair is not your actual use case.
There was a time when having identically named functions was the convention for default constructors; this convention fell out of favour as time went by. It is considered bad form nowadays, probably mostly for consistency. If you have a tuple struct (or variant) Pair(T, U), then you can use Pair(first, last) in a pattern, but if you have Pair { first: T, last: U } then you would need to use something more like Pair { first, last } in a pattern, and so your Pair(first, last) function would be inconsistent with the pattern. It is generally felt, thus, that these type of camel-case functions should be reserved solely for tuple structs and tuple variants, where it can be known that it is genuinely reflecting what is contained in the data structure with no further processing or magic.

How to rewrite Vec.append "in favor of" extend?

When the following is submitted to the compiler
fn main()
{
let abc = vec![10u, 20u, 30u];
let bcd = vec![20u, 30u, 40u];
let cde = abc.append(bcd.as_slice());
println!("{}", cde);
}
the compiler emits the following warning:
this function has been deprecated in favor of extend()
How would the equivalent look using extend?
Take a look at the signature for extend:
fn extend<I: Iterator<T>>(&mut self, iterator: I)
Note that it takes self by a mutable reference, and that it doesn’t take a slice but rather an iterator (which is more general-purpose).
The end result would look like this, then:
abc.extend(bcd.into_iter());
Or this:
abc.extend(bcd.iter().map(|&i| i))
(Bearing in mind that Vec.iter() produces something that iterates over references rather than values, hence the need for .map(|&i| i).)
I am a little surprised that it is recommending extend, as push_all is a much more direct replacement, taking a slice rather than an iterator:
abc.push_all(bcd.as_slice());

Resources