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

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(). )

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.

Initialize Gstreamer's PadProbeId to a default value in Rust

I am familiar with Gstreamer but new to Rust,
TLDR; I want to be able to initialize PadProbeId to a default value before using it.
The details:
I have a Bin (containing audio + video encoders and hlssink).
I have been able to add this bin to the pipeline and it works fine.
The issue I have is the audio for the stream is optional and I want to do add_probe() only when audio is available. Below is a simplified version fo what I tried to implement
let mut audio_probe_id: PadProbeId;
let mut tee_audio_pad: Pad;
if media_info.audio_available {
// get encoded audio from the tee
tee_audio_pad = audio_tee.request_pad_simple("src_%u").unwrap();
audio_probe_id = tee_audio_pad.add_probe(gst::PadProbeType::BLOCK_DOWNSTREAM, |_pad, _info| {
gst::PadProbeReturn::Ok
}).unwrap();
// link the audio_tee.src to enc_bin ghost pad
let audio_sink_pad = enc_bin.static_pad("audio").unwrap();
tee_audio_pad.link(&audio_sink_pad).unwrap();
}
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
if media_info.audio_available {
tee_audio_pad.remove_probe(audio_probe_id);
}
}
However because of Rust compilers restriction to using uninitialized variables, it does not let me use audio_probe_id without initializing.
I tried to initialize it like this; let mut audio_probe_id: PadProbeId = PadProbeId(NonZeroU64(u64::MAX));. However compiler complains that it is a private field.
error[E0423]: cannot initialize a tuple struct which contains private fields
Thanks a lot for your help!
The rust way to have empty variables like this is to use Option, but in your case it would simpler to have a single conditional:
if media_info.audio_available {
// get encoded audio from the tee
let tee_audio_pad = audio_tee.request_pad_simple("src_%u").unwrap();
let audio_probe_id = tee_audio_pad.add_probe(gst::PadProbeType::BLOCK_DOWNSTREAM, |_pad, _info| {
gst::PadProbeReturn::Ok
}).unwrap();
// link the audio_tee.src to enc_bin ghost pad
let audio_sink_pad = enc_bin.static_pad("audio").unwrap();
tee_audio_pad.link(&audio_sink_pad).unwrap();
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
tee_audio_pad.remove_probe(audio_probe_id);
}
} else {
enc_bin.call_async(move |bin| {
bin.sync_state_with_parent().unwrap();
});
}

Using wasm_timer in Yew to execute callback repeatedly

I'm still rather new to Rust and have a hard time wrapping my head around futures. I want to implement a "timer app" in the browser and to do so I'm using https://yew.rs/. For the timer I tried to use https://github.com/tomaka/wasm-timer/, but there are not docs and no examples. Looks like the usage is supposed to be obvious, but I don't get it.
I assume that I have to do something like:
let i = Interval::new(core::time::Duration::from_millis(250));
This should create an Interval that fires every 250ms. But what is fired? How to I specify my callback? I would expect something like:
i.somehow_specify_callback(|| { ... executed every 250ms ...});
My feeling is, that I'm somehow on the wrong path and do not get grasp Rust futures. A working example on how to make an Interval execute some code would be very appreciated.
Here is a pseudo code example for Timer component:
enum SecondsStateAction {
Increment,
}
#[derive(Default)]
struct SecondsState {
seconds: usize,
}
impl Reducible for SecondsState {
/// Reducer Action Type
type Action = SecondsStateAction;
/// Reducer Function
fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
match action {
SecondsStateAction::Increment => Self { seconds: self.seconds + 1 }.into(),
}
}
}
#[function_component(Timer)]
pub fn timer() -> Html {
let seconds_state_handle = use_reducer(SecondsState::default);
use_effect_with_deps(
{
let seconds_state_handle = seconds_state_handle.clone();
move |_| {
// i intervals get out of scope they get dropped and destroyed
let interval = Interval::new(1000, move || seconds_state_handle.dispatch(SecondsStateAction::Increment));
// So we move it into the clean up function, rust will consider this still being used and wont drop it
// then we just drop it ourselves in the cleanup
move || drop(interval)
}
},
(), // Only create the interval once per your component existence
);
html! {<h1>{*seconds_state_handle}{" seconds has passed since this component got rendered"}</h1>}
}
to learn more about the hooks i used in the code visit https://yew.rs/docs/concepts/function-components/pre-defined-hooks

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

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!

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()
}

Resources