Issue when creating a Vector and assigning it later on [closed] - rust

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
After reading a LOT of documentation I figured out that I am facing a problem of scope, but I have no idea how to solve it. See the example code below:
fn main() {
let mut bytes_buf:Vec<u8> = Vec::new(); // 1) where I declare the Vector, the compiler force me to initialize it.
loop {
match socket.recv_from(&mut buf) {
Ok((size, src)) => {
if count == 0 {
chunks_cnt = ...
bytes_buf = vec![0; MAX_CHUNK_SIZE * chunks_cnt as usize]; // 2) where I want to set vector size, only ONCE, and after knowing chunks_cnt
}
bytes_buf[start..end].copy_from_slice(buf); // 3) where I want to gradually fill the vector
}
}
}
}
For convenience, you can check the full code here

Possible solution
Here the socket fills the slice buf. If it fails an error message is shown. If is succeeds it will enter the loop.
On each iteration of the loop, the buf is converted to a Vec<u8> and appended to bytes_buf. Then if this is the first iteration, then the size value is inserted into the first position. Then the first flag is set to false. After that all iterations will continue appending data to the vector.
The following minimal example should compile fine:
use std::net::{UdpSocket};
const UDP_HEADER: usize = 8;
const IP_HEADER: usize = 20;
const MAX_DATA_LENGTH: usize = (64 * 1024 - 1) - UDP_HEADER - IP_HEADER;
fn main() {
let socket = UdpSocket::bind("0.0.0.0:8888").expect("Could not bind socket");
let mut buf= [0u8; MAX_DATA_LENGTH]; // Slice that will be filled by recv_from.
let mut bytes_buf:Vec<u8> = Vec::new(); // Vector where the data will be moved.
let mut first = true; // Flag that indicates if this is our first iteration.
loop {
match socket.recv_from(&mut buf) {
Ok((_size, _src)) => {
// Convert the slice to a vector (to_vec function) and append it to the bytes_buf.
bytes_buf.append(&mut buf.to_vec());
if first {
// Insert function inserts the element at the specified position and shifts
// all elements after it to the right.
bytes_buf.insert(0, 10u8); // IDK What value you need here.
}
first = false; // Set first to false
},
Err(err) => eprintln!("Error: {}", err) // If we fail display the error.
}
}
}
Side note
Your example was missing lots of variables and context. Despite this, I managed to create a minimal working example of what I believe you are trying to achieve thanks to the link you shared despite being quite different. Please next time provide a minimal reproducible example. More information here: How to create a Minimal, Reproducible Example
Have a nice day!

Related

How do I extract hex values as strings? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
This post was edited and submitted for review 4 days ago.
Improve this question
I am trying to extract a hash value from a function output:
let receipt = do_something();
println!("{receipt:?}");
let receipt_txn_hash = receipt.transaction_hash;
println!("receipt_txn_hash: {}", receipt_txn_hash);
let tx = provider.get_transaction(receipt_txn_hash).await?;
println!("tx: {}\n", serde_json::to_string(&tx)?);
let tx_hash = if let Some(txn) = tx {
txn.hash.to_string()
} else {
"hash_not_found".to_owned() //H256([0; 32])
};
println!("tx.hash: {}\n", &tx_hash);
And it prints out in the terminal:
TransactionReceipt { transaction_hash: 0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7, ... }
receipt_txn_hash: 0xd6a0…f3b7
tx: {"hash":"0xd6a0e48e6a0f80ae4467193f40721da1ad53ec854a738ea57d7201619e60f3b7",...}
tx.hash: 0xd6a0…f3b7
Somehow Rust-Analyzer identifies this receipt has {unknown} type, but tx has Option<Transaction> type.
But still, both the receipt.transaction_hash, tx.hash have been truncated... *why?
How can I get the original complete hash value and return it as a String?
Here are the dependencies:
ethers = { version = "1.0.2", features = ["legacy", "rustls"] }
ethers-solc = { version = "1.0.2", features = ["full"] }
ethers-providers = "1.0.2"
eyre = "0.6.8"
hex = "0.4.3"
reqwest = { version = "0.11.14", default-features = false }
serde_json = "1.0.93"
[Update]
Thanks to the answer below, both receipt_txn_hash and tx_hash are of the type H256.
The Display trait of H256 type is defined here:
https://github.com/paritytech/parity-common/blob/223af1dc6c176e35698aed9285f44e428da0050e/fixed-hash/src/hash.rs#L217
impl $crate::core_::fmt::Display for $name {
fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result {
$crate::core_::write!(f, "0x")?;
for i in &self.0[0..2] {
$crate::core_::write!(f, "{:02x}", i)?;
}
$crate::core_::write!(f, "…")?;
for i in &self.0[$n_bytes - 2..$n_bytes] {
$crate::core_::write!(f, "{:02x}", i)?;
}
Ok(())
}
}
From the Display trait definition above, we know Display trait is causing the truncation.
So we need to modify the Display trait(defined in our dependencies).
But we cannot modify or override the foreign trait definition due to: only traits defined in the current crate can be implemented for types defined outside of the crate. Define and implement a trait or new type instead
So we have to make our local type to modify the foreign trait!
Hence, this question is basically asking how to implement a local type(NewH256), on a foreign trait(fmt::Display)?
Going by a quick search I'm guessing the type is a H256 from here.
This has a Display implementation here which gives you your ellipses.
If you want to show the full hex, you might be best just printing the debug output:
println!("receipt_txn_hash: {:?}", receipt_txn_hash);
If that doesn't work, you can just copy the Display impl and format it however you want.

Do i have to create a copy of objects for threads need [duplicate]

This question already has an answer here:
How can I pass a reference to a stack variable to a thread?
(1 answer)
Closed 1 year ago.
I created a two methods one synchronous and one with multiple threads because I wanted to compare performance synchronous and parallel method. But I am having a one issue every time when I want to use my data in threads I have to copy them first even if I know that they want to be dropped till the end of this method. If I do not copy this data before using in threads then I am getting an error that I have to make my data 'static:
fn parallel_kronecker_product(&self, matrix: &Matrix) -> Matrix {
let product_rows = self.rows_count * matrix.rows_count;
let product_columns_count = self.columns_count * matrix.columns_count;
let product = Arc::new(Mutex::new(Matrix::new_zeros_matrix(
product_rows,
product_columns_count,
)));
let mut handles = vec![];
for m1_row_index in 0..self.rows_count {
let product = Arc::clone(&product);
let matrix_a = self.to_owned();
let matrix_b = matrix.to_owned();
handles.push(
thread::spawn(move || {
for m1_column_index in 0..matrix_a.columns_count {
for m2_row_index in 0..matrix_b.rows_count {
for m2_column_index in 0..matrix_b.columns_count {
let product_row_index = m1_row_index * matrix_b.rows_count + m2_row_index;
let product_column_index =
m1_column_index * matrix_b.columns_count + m2_column_index;
let mut prod = product.lock().unwrap();
(*prod)[product_row_index][product_column_index] = matrix_a[m1_row_index]
[m1_column_index]
* matrix_b[m2_row_index][m2_column_index];
}
}
}
})
);
}
for handle in handles {
handle.join().unwrap();
}
return product.lock().unwrap().clone();
}
So here I have two matrices. Base which is immutable self and one from parameter matrix. Inside for m2_row_index in 0..matrix_b.rows_count loop I am only multiplying some data which doesn't change original data. Then I iterate over all threads to tell rust to wait until all threads finish their job, so nothing outside this method scope should drop this matrix
Can you tell me, what can I do to do not copy this data?
You can use a scoped thread from a third party crate. There are a few to choose from, but a popular one is from crossbeam. The reason this is needed is because the types used for threads spawned with std::thread::spawn do not carry information about how long they last, even if you are explicitly joining them. Crossbeam's scoped threads are bound to the lifetime of the surrounding Scope so the borrow checker can be sure that they are finished with borrowed data when the scope ends.
Your provided code has a lot of definitions missing, so I didn't try to compile it, but the general idea would be this:
fn parallel_kronecker_product(&self, matrix: &Matrix) -> Matrix {
// Create a new thread scope and make it own the locals
thread::scope(move |scope| {
let product_rows = self.rows_count * matrix.rows_count;
let product_columns_count = self.columns_count * matrix.columns_count;
let product = Arc::new(Mutex::new(Matrix::new_zeros_matrix(
product_rows,
product_columns_count,
)));
let mut handles = vec![];
for m1_row_index in 0..self.rows_count {
let product = Arc::clone(&product);
let matrix_a = self.to_owned();
let matrix_b = matrix.to_owned();
// spawn a new thread inside the scope which owns the data it needs to borrow
handles.push(scope.spawn(move |_| {
for m1_column_index in 0..matrix_a.columns_count {
for m2_row_index in 0..matrix_b.rows_count {
for m2_column_index in 0..matrix_b.columns_count {
let product_row_index =
m1_row_index * matrix_b.rows_count + m2_row_index;
let product_column_index =
m1_column_index * matrix_b.columns_count + m2_column_index;
let mut prod = product.lock().unwrap();
(*prod).ind();
}
}
}
}));
}
for handle in handles {
handle.join().unwrap();
}
// probably need a new local binding here. For... reasons...
let product = product.lock().unwrap().clone();
product
}).unwrap()
}

How do I spawn children into an existing component? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Assume I have something like this:
use bevy::prelude::*;
// Bevy style tag
struct &CharacterBox;
// Somewhere to store the entity
pub struct Action {
pub character_box: Option<Entity>,
};
fn setup( mut commands: Commands, mut action: ResMut<Action> ) {
if let Some(entity) = commands
.spawn(UiCameraComponents::default())
.spawn(NodeComponents { /* snip */ })
.with_children(|p| {
p.spawn(ButtonComponents { /* snip, snap */ });
})
.with(CharacterBox)
.current_entity()
{
action.character_box = Some(entity);
}
}
A NodeComponents with a button or two from startup...
...and later I want to add more buttons from a system I've added:
fn do_actions(
mut commands: Commands,
action: ChangedRes<Action>,
mut query: Query<(&CharacterBox, &Children)>,
) {
if let Some(entity) = commands
.spawn(ButtonComponents { /* ... */ })
.current_entity()
{
let mut charbox = query.get_mut::<Children>(action.character_box.unwrap()).unwrap();
// I know this is naïve, I know I can't just push in the entity,
// but it illustrates my point...
charbox.push(entity); // How do I achieve this?
}
}
How do insert my spawned entity (component?) into my NodeComponents.Children?
How do I spawn a component into an already existing component?
Or how do I access NodeComponents.Children.ChildBuilder? Can I query ChildBuilders?
Edit: removed edits.
Anyway, here is how I solved it:
let parent_entity = action.character_box.unwrap();
let new_entity = commands
.spawn(ButtonComponents { /* ... */ })
.current_entity()
.unwrap();
commands.push_children(parent_entity, &[c]);
(With nested NodeComponents, I had to spawn them seperately, and then push each entity into the other, because to my knowledge there is no way to get the entity from a ChildBuilder, only by using commands.spawn(...).current_entity(). )

Why can't hash_map::Entry::or_insert_with access the entry's key? [duplicate]

This question already has answers here:
How do I use the Entry API with an expensive key that is only constructed if the Entry is Vacant?
(2 answers)
How can I get a reference to the key and value immediately after inserting into a `HashMap`?
(1 answer)
Closed 3 years ago.
I'm trying to efficiently look up or insert an item into a HashMap that owns both its keys and its values.
According to How to lookup from and insert into a HashMap efficiently?, the Entry API is the way to do this.
However, when inserting a new item, I also need access to the key.
Since HashMap::entry consumes the key, I cannot do the following, which fails with error[E0382]: borrow of moved value: 'index':
let mut map: HashMap<String, Schema> = ...;
let index: String = ...;
let schema = map
.entry(index)
.or_insert_with(|| Schema::new(&index));
The simplest way to get this working seems to be as follows:
let schema = match map.entry(index) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => {
// VacantEntry::insert consumes `self`,
// so we need to clone:
let index = e.key().to_owned();
e.insert(Schema::new(&index))
}
};
If only or_insert_with would pass the Entry to the closure that it calls, it would have been possible to write the above code like this:
let schema = map
.entry(index)
.or_insert_with_entry(|e| {
let index = e.key().to_owned();
Schema::new(&index)
});
Did I overlook something? What would be the best way to write this code?

Why is this hashmap search slower than expected?

What is the best way to check a hash map for a key?
Currently I am using this:
let hashmap = HashMap::<&str, &str>::new(); // Empty hashmap
let name = "random";
for i in 0..5000000 {
if !hashmap.contains_key(&name) {
// Do nothing
}
}
This seems to be fast in most cases and takes 0.06 seconds when run as shown, but when I use it in this following loop it becomes very slow and takes almost 1 min on my machine. (This is compiling with cargo run --release).
The code aims to open an external program, and loop over the output from that program.
let a = vec!["view", "-h"]; // Arguments to open process with
let mut child = Command::new("samtools").args(&a)
.stdout(Stdio::piped())
.spawn()
.unwrap();
let collect_pairs = HashMap::<&str, &str>::new();
if let Some(ref mut stdout) = child.stdout {
for line in BufReader::new(stdout).lines() {
// Do stuff here
let name = "random";
if !collect_pairs.contains_key(&name) {
// Do nothing
}
}
}
For some reason adding the if !collect_pairs.contains_key( line increases the run time by almost a minute. The output from child is around 5 million lines. All this code exists in fn main()
EDIT
This appears to fix the problem, resulting in a fast run time, but I do not know why the !hashmap.contains_key does not work well here:
let n: Option<&&str> = collect_pairs.get(name);
if match n {Some(v) => 1, None => 0} == 1 {
// Do something
}
One thing to consider is that HashMap<K, V> uses a cryptographically secure hashing algorithm by default, so it will always be a bit slow by nature.
get() boils down to
self.search(k).map(|bucket| bucket.into_refs().1)
contains_key is
self.search(k).is_some()
As such, that get() is faster for you seems strange to me, it's doing more work!
Also,
if match n {Some(v) => 1, None => 0} == 1 {
This can be written more idiomatically as
if let Some(v) = n {
Ive found my problem, Im sorry I didnt pick up until now. I wasnt checking the return of if !collect_pairs.contains_key(&name) properly. It returns true for some reason resulting in the rest of the if block being run. I assumed it was evaluating to false. Thanks for the help

Resources