How to create a vector of a specific number of Results? - rust

I am trying to send a stream of data with a specific size without the content length header. I believe hyper::body::Body::wrap_stream is what I'm looking for. However, I'm not sure how to extend the example of creating a vector of results given in documentation to incorporate a custom size.
I'm looking for something like this, but I don't know the best way to resolve issues with vec![Ok(0); bytes].
let chunks: Vec<Result<_, std::io::Error>> = vec![Ok(0); bytes];
let stream = futures_util::stream::iter(chunks);
let body = Body::wrap_stream(stream);

The problem here is that Result does not implement Clone so you can't use this syntax to initialize the Vec.
You can make it work by changing it as follow:
let mut chunks: Vec<Result<_, std::io::Error>> = Vec::new();
chunks.resize_with(bytes, || Ok(0));
This way, you initialize independent Result values.

Related

Re-use already advanced iterator for different function

While iterating over lines in a file I need to first do "task_A" and then "task_B". The first few lines there is some data that I need to put into some data structure (task_A) and after that the lines describe how the data inside of the data structure is manipulated (task_B). Right now I use a for-loop with enumerate and if-else statements that switch depending on which file number:
let file = File::open("./example.txt").unwrap();
let reader = BufReader::new(file);
for (i, lines) in reader.lines().map(|l| l.unwrap()).enumerate() {
if i < n {
do_task_a(&lines);
} else {
do_task_b(&lines);
}
}
There is also the take_while()-method for iterators. But this only solves one part. Ideally I would pass the iterator for n steps to one function and after that to another function. I want to have a solution that only needs to iterate over the file one time.
(For anyone wondering: I want a more elegant solution for 5th day of Advent of Code 2022 Is there a way to do that? To "re-use" the iterator when it is already advanced n steps?
Looping or using an iterator adapter will consume an iterator. But if I is an iterator then so is &mut I!
You can use that instance to partially iterate through the iterator with one adapter and then continue with another. The first use consumes only the mutable reference, but not the iterator itself. For example using take:
let mut it = reader.lines().map(|l| l.unwrap());
for lines in (&mut it).take(n) {
do_task_a(&lines);
}
for lines in it {
do_task_b(&lines);
}
But I think your original code is still completely fine.

str ops into existing Vec

Most operations on str in Rust create newly-allocated Strings. I understand that, because UTF8 is complex, one cannot generally know beforehand the size of the output, and so that output must be growable. However, I might have my own buffer , such as a Vec<u8> I'd like to grow. Is there any way to specify an existing output container to string operations?
e.g.,
let s = "my string";
let s: Vec<u8> = Vec::with_capacity(100); // explicit allocation
s.upper_into(s); // perhaps new allocation here, if result fits in `v`
-EDIT-
This is, of course, just for one case. I'd love to be able to treat all of the str methods this way, including for example those in sentencecase , without having to copy their internal logic.
You can walk char-by-char and use char::to_uppercase():
let mut uppercase = String::with_capacity(100);
uppercase.extend(s.chars().flat_map(char::to_uppercase));
I think it does not handle everything correctly, but this is exactly what str::to_uppercase() does too, so I assume it's OK.

Rust executing methods concurrently

I'm trying to learn rust and have some issues when trying to work with streams of futures. I have the following code
// Stocks: Vec<Stock> || Stock is my struct that implements method get_stock_depth
let futures = stocks.iter();
let futures = futures.map(|x| x.get_stock_depth());
let stream = stream::iter(futures);
let stream = stream.buffer_unordered(10);
let result = stream.collect().await;
Stocks vector contains over 800 objects and i figured I'd like to limit concurrent executions. When i'm running the following code i get the following error
type inside async block must be known in this context cannot infer
type for type parameter C declared on the associated function
collect
Am i missing something?
This almost certainly has nothing to do with async or futures. This is just the normal requirement for collect to provide a type. collect() can create a number of return types and doesn't know what you want. You probably want a Vec like:
let result: Vec<_> = stream.collect().await;
You don't typically need to tell collect what to fill the Vec with (it can usually figure that out), so you can use _, but you do need to tell it what collection type you want.
You might also write this as:
let result = stream.collect::<Vec<_>>().await;
Or if this is the last line of a function that returns result, you can use type inference on the return type by dropping the assignment and the semicolon:
stream.collect().await

Get amount of elements in a HashMap

I would like to know how to get the amount of elements in a HashMap with rust.
I'm currently using this to check if a HashMap is empty or not, so if there is a more idiomatic way to get that as well, I would love to know both.
std::HashMap has a len method to check for the number of elements, but you can use is_empty method to check if it contains any items.
let mut map = HashMap::new();
assert!(map.is_empty());
assert_eq!(map.len(), 0);
a.insert(1, "a");
assert!(!map.is_empty());
assert_eq!(map.len(), 1);

Incrementally build data structures which reference the same data

I have an EntityMap object which deals with spatially indexing anything that can have a bounding box. I've implemented it in such a way that it stores references to objects rather than owned values (this may not be the best way to do, but I think changing it to owned values would only shift my problem).
What I am currently attempting to do is add objects to a vector in such a way that they do not collide with anything that was previously added to the vector. The following is pseudo-rust of what I just described:
let mut final_moves = Vec::new();
let mut move_map = EntityMap::new();
for m in moves.into_iter() {
let close_moves = move_map.find_intersecting(m.bounding_box());
let new_move = m.modify_until_not_intersecting(close_moves);
final_moves.push(new_move);
move_map.insert(final_moves.last().unwrap());
}
final_moves is what is being returned from the function. The issue here is that I'm mutably borrowing final_moves, but I want to store references to its objects inside move_map. The conflict I can't figure out how to resolve is that I want to incrementally build final_moves and move_map at the same time, but this seems to require that they both be mutable, which then stops me from borrowing data from move_map.
How do I restructure my code to accomplish my goals?
You could change the types of move_map and final_moves to contain Rc<Move> instead of just Move.
let mut final_moves = Vec::new();
let mut move_map = EntityMap::new();
for m in moves.into_iter() {
let close_moves = move_map.find_intersecting(m.bounding_box());
let new_move = Rc::new(m.modify_until_not_intersecting(close_moves));
final_moves.push(Rc::clone(new_move));
move_map.insert(new_move);
}

Resources