Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
use sha3::{Digest, Keccak256};
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
let vote_commit_bytes: &[u8] = &vote_commit;
if &result[..] == vote_commit_bytes {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
println!("commit: {:?}", commit);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
Want to check the hash matches, but both hash and string are in Vec<u8>,
but &result[..] == vote_commit_bytes doesnot match. How to check the equality?
https://docs.rs/sha3/0.9.1/sha3/
There is no equality, because apparently the format!() macro alters the data in some way (which I think is not totally unexpected).
The {:x} formatting option, formats the data as:
Debug with lower-case hexadecimal integers
so that is why those representations are not equal.
If you format both hash results in your code, it works as expected:
use sha3::{Digest, Keccak256};
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
let vote_commit_bytes: &[u8] = &vote_commit;
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
if commit.as_bytes().to_vec() == vote_commit_bytes {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
println!("commit: {:?}", commit);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
Sorry, old question, solved it using hex
use sha3::{Digest, Keccak256};
use hex;
fn reveal_vote(mut voter_id: Vec<u8>, mut phrase: Vec<u8>, vote_commit: Vec<u8>) {
let mut hyphen_vec = "-".as_bytes().to_vec();
voter_id.append(&mut hyphen_vec);
voter_id.append(&mut phrase);
let vote_bytes: &[u8] = &voter_id;
let mut hasher = Keccak256::new();
hasher.update(vote_bytes);
let result = hasher.finalize();
if hex::encode(result).as_bytes().to_vec() == vote_commit {
println!("Data matched");
} else {
println!("data mismatched")
}
}
fn main() {
let vote_commit_string = "1-abcdef".as_bytes().to_vec();
let mut hasher = Keccak256::new();
hasher.update(vote_commit_string);
let result = hasher.finalize();
println!("{:?}", result);
println!("{:?}", &result[..]);
let commit = format!("{:x}", result); // e2a18e9b74f228590ca8c563cecfc58c28455b2dde25b4bbdc663e99e791f47c
let commit_vec = commit.as_bytes().to_vec();
// println!("commit: {:?}", commit);
println!("commit_vec: {:?}", commit_vec);
reveal_vote("1".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(), commit_vec);
}
Related
I'm writing a program that detects duplicate frames in h264 encoded video. I'm using the ac-ffmpeg crate Here's my code:
use std::fs::File;
use ac_ffmpeg::{
codec::{
video::{frame::Planes, VideoDecoder},
CodecParameters, Decoder,
},
format::{
demuxer::{Demuxer, DemuxerWithStreamInfo},
io::IO,
muxer::{Muxer, OutputFormat},
},
Error,
};
fn open_input(path: &str) -> Result<DemuxerWithStreamInfo<File>, Error> {
let input = File::open(path)
.map_err(|err| Error::new(format!("unable to open input file {}: {}", path, err)))?;
let io = IO::from_seekable_read_stream(input);
Demuxer::builder()
.build(io)?
.find_stream_info(None)
.map_err(|(_, err)| err)
}
fn open_output(path: &str, elementary_streams: &[CodecParameters]) -> Result<Muxer<File>, Error> {
let output_format = OutputFormat::guess_from_file_name(path)
.ok_or_else(|| Error::new(format!("unable to guess output format for file: {}", path)))?;
let output = File::create(path)
.map_err(|err| Error::new(format!("unable to create output file {}: {}", path, err)))?;
let io = IO::from_seekable_write_stream(output);
let mut muxer_builder = Muxer::builder();
for codec_parameters in elementary_streams {
muxer_builder.add_stream(codec_parameters)?;
}
muxer_builder.build(io, output_format)
}
fn plane_difference(planes1: &Planes, planes2: &Planes) -> u64 {
6
}
fn remove_duplicate_frames(input: &str, output: &str) -> Result<(), Error> {
let mut demuxer = open_input(input)?;
let (stream_index, (stream, _)) = demuxer
.streams()
.iter()
.map(|stream| (stream, stream.codec_parameters()))
.enumerate()
.find(|(_, (_, params))| params.is_video_codec())
.ok_or_else(|| Error::new("no video stream"))?;
let mut decoder = VideoDecoder::from_stream(stream)?.build()?;
let mut packet_count = 0;
let mut prev_planes: Option<Planes> = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_planes {
Some(prev) => {
let diff = plane_difference(&planes, &prev);
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_planes = Some(planes);
}
if packet_count > 2000 {
break;
}
packet_count += 1;
}
diffs.sort_by(|a, b| b.1.cmp(&a.1));
dbg!(diffs);
Ok(())
}
with dependency ac-ffmpeg = "0.17.4".
The problem is this gives an error that frame does not live long enough:
error[E0597]: `frame` does not live long enough
--> src/main.rs:106:26
|
106 | let planes = frame.planes();
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
107 |
108 | match prev_planes {
| ----------- borrow later used here
...
117 | }
| - `frame` dropped here while still borrowed
My understanding of this error is that frame is borrowed, which via planes ends up in prev_planes. But at the end of every loop the value is dropped so it doesn't exist for the next iteration. Is that correct? And how can I solve that? I tried cloning various things in this code but I'm not able to fix the error.
VideoFrame doesn't allow you to take the planes, it only allows you to borrow them from the frame.
You can see that because a lifetime is attached to the planes:
pub fn planes(&self) -> Planes<'_>
The '_ lifetime says it's identical to the lifetime of the &self reference, meaning it is borrowed from self.
If you want to store the planes, store the frame that contains them instead:
use std::fs::File;
use ac_ffmpeg::{
codec::{
video::{frame::Planes, VideoDecoder, VideoFrame},
CodecParameters, Decoder,
},
format::{
demuxer::{Demuxer, DemuxerWithStreamInfo},
io::IO,
muxer::{Muxer, OutputFormat},
},
Error,
};
fn open_input(path: &str) -> Result<DemuxerWithStreamInfo<File>, Error> {
let input = File::open(path)
.map_err(|err| Error::new(format!("unable to open input file {}: {}", path, err)))?;
let io = IO::from_seekable_read_stream(input);
Demuxer::builder()
.build(io)?
.find_stream_info(None)
.map_err(|(_, err)| err)
}
fn open_output(path: &str, elementary_streams: &[CodecParameters]) -> Result<Muxer<File>, Error> {
let output_format = OutputFormat::guess_from_file_name(path)
.ok_or_else(|| Error::new(format!("unable to guess output format for file: {}", path)))?;
let output = File::create(path)
.map_err(|err| Error::new(format!("unable to create output file {}: {}", path, err)))?;
let io = IO::from_seekable_write_stream(output);
let mut muxer_builder = Muxer::builder();
for codec_parameters in elementary_streams {
muxer_builder.add_stream(codec_parameters)?;
}
muxer_builder.build(io, output_format)
}
fn plane_difference(planes1: &Planes, planes2: &Planes) -> u64 {
6
}
fn remove_duplicate_frames(input: &str, output: &str) -> Result<(), Error> {
let mut demuxer = open_input(input)?;
let (stream_index, (stream, _)) = demuxer
.streams()
.iter()
.map(|stream| (stream, stream.codec_parameters()))
.enumerate()
.find(|(_, (_, params))| params.is_video_codec())
.ok_or_else(|| Error::new("no video stream"))?;
let mut decoder = VideoDecoder::from_stream(stream)?.build()?;
let mut packet_count = 0;
let mut prev_frame: Option<VideoFrame> = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_frame {
Some(prev) => {
let diff = plane_difference(&planes, &prev.planes());
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_frame = Some(frame);
}
if packet_count > 2000 {
break;
}
packet_count += 1;
}
diffs.sort_by(|a, b| b.1.cmp(&a.1));
dbg!(diffs);
Ok(())
}
You need to keep the frame itself from one loop iteration to the next instead of the planes. So have a prev_frame variable instead of prev_planes:
let mut prev_frame = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_frame {
Some(prev) => {
let diff = plane_difference(&planes, &prev.planes());
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_frame = Some(frame);
}
}
It's a bit tricky to reproduce this, so I'll try to answer from the top of my head.
Did you try:
let planes = frame.planes().to_owned();
Mainly you're giving ownership of planes (i.e. the child), while the parent (frame) goes out of scope.
Why to_owned? (if the child is a ref, clone will return a ref, so we use to_owned instead since it converts a ref type to an owned type where it's allowed to transfer ownership.
The solution should be either:
let planes = frame.planes().to_owned(); // line 106
or
prev_planes = Some(planes.clone()); // line 116
If none of these work, try updating your question with their outputs. It'll make it easier to answer.
This is part of my code
pub async fn json_to(info: web::Json<Info>, data: web::Data<AppState>) -> String {
let pool = data.pool_redis.clone();
let conn = pool.get().await.unwrap();
let mut a = conn.cluster.clone().unwrap();
let redis_handle = RedisHandle::new(a);
let user = redis_handle
.get_user(
info.u_id.to_string(),
vec!["guild_positions", "guild_pending", "guild_folders"],
)
.await;
let lists: Vec<String> = serde_json::from_str(&guild_position).unwrap();
let v8 = vec!["1".to_string(), "2".to_string()];
// let v8: Vec<&str> = v8.iter().map(move |x| x.as_str()).collect();
let v8: Vec<&str> = lists.iter().map(|x| x.as_str()).collect();
let my_nicks = redis_handle
.get_user_guild_nick(info.u_id.clone().to_string(), v8)
.await
.unwrap();
format!("done")
In let v8: Vec<&str> = lists.iter().map(|x| x.as_str()).collect(); an error will be displayed
But if it’s okay
let v8 = vec!["1".to_string(), "2".to_string()];
let v8: Vec<&str> = v8.iter().map(move |x| x.as_str()).collect();
How should I use lists without prompting ownership
This is the get_user_guild_nick function
pub async fn get_user_guild_nick(
&self,
user_id: String,
fields: Vec<&'static str>,
) -> Result<HashMap<&'static str, Option<String>>> {
let mut _con = self.connect.clone();
let key = KEYMAP["user_nick"].replace("%s1", &user_id);
let result: Vec<Option<String>> = cmd("hmget")
.arg(key)
.arg(&fields)
.query_async(&mut _con)
.await
.unwrap_or(vec![None]);
let mut map: HashMap<&'static str, Option<String>> = HashMap::new();
let iter = fields.iter().enumerate();
for (k, v) in iter {
map.insert(v, result[k].clone());
}
Ok(map)
}
You have to remove static life time in fields params.
pub async fn get_user_guild_nick(
&self,
user_id: String,
fields: Vec<&str>, //<---HERE
) -> Result<HashMap<&'static str, Option<String>>> {
let mut _con = self.connect.clone();
let key = KEYMAP["user_nick"].replace("%s1", &user_id);
let result: Vec<Option<String>> = cmd("hmget")
.arg(key)
.arg(&fields)
.query_async(&mut _con)
.await
.unwrap_or(vec![None]);
let mut map: HashMap<&'static str, Option<String>> = HashMap::new();
let iter = fields.iter().enumerate();
for (k, v) in iter {
map.insert(v, result[k].clone());
}
Ok(map)
}
I get this error while compiling my code: please help me.
use of moved value: `path`
value used here after moverustc(E0382)
main.rs(16, 9): move occurs because `path` has type `std::result::Result`, which does not implement the `Copy` trait
main.rs(18, 32): `path` moved due to this method call
main.rs(19, 29): value used here after move
fn main() -> std::io::Result<()> {
let paths = fs::read_dir("./").unwrap();
let mut text = String::new();
let mut idx = 0;
for path in paths {
// let path_str = path.unwrap().path().display().to_string();
let path_str = if path.unwrap().path().is_dir() {
path.unwrap().path().display().to_string()
}
else {
let mut path = path.unwrap().path().display().to_string();
path.push_str("[file]");
path
};
let path_trimed = path_str.trim_start_matches("./");
idx += 1;
println!("{} -> file/folder: {}", idx + 1, path_trimed);
text.push_str(&path_trimed);
text.push_str("\n");
}
// println!("{}", text);
// writing the string to file
let mut file = fs::File::create("file_list.txt")?;
file.write_all(&text.as_bytes())?;
Ok(())
}
I think the problem is that you're unwrapping path many times, each unwrapping borrows the variable path, so you rust will complain when you try to unwrap a second time.
I suggest you try to unwrap it just once:
use std::fs;
use std::io::Write;
fn main() -> std::io::Result<()> {
let paths = fs::read_dir("./").unwrap();
let mut text = String::new();
let mut idx = 0;
for path in paths {
// let path_str = path.unwrap().path().display().to_string();
let path = path.unwrap().path();
let path_str = if path.is_dir() {
path.display().to_string()
} else {
let mut path = path.display().to_string();
path.push_str("[file]");
path
};
let path_trimed = path_str.trim_start_matches("./");
idx += 1;
println!("{} -> file/folder: {}", idx + 1, path_trimed);
text.push_str(&path_trimed);
text.push_str("\n");
}
// println!("{}", text);
// writing the string to file
let mut file = fs::File::create("file_list.txt")?;
file.write_all(&text.as_bytes())?;
Ok(())
}
This question already has an answer here:
How to send a pointer to another thread?
(1 answer)
Closed 5 months ago.
I was able to proceed forward to implement my asynchronous udp server. However I have this error showing up twice because my variable data has type *mut u8 which is not Send:
error: future cannot be sent between threads safely
help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*mut u8`
note: captured value is not `Send`
And the code (MRE):
use std::error::Error;
use std::time::Duration;
use std::env;
use tokio::net::UdpSocket;
use tokio::{sync::mpsc, task, time}; // 1.4.0
use std::alloc::{alloc, Layout};
use std::mem;
use std::mem::MaybeUninit;
use std::net::SocketAddr;
const UDP_HEADER: usize = 8;
const IP_HEADER: usize = 20;
const AG_HEADER: usize = 4;
const MAX_DATA_LENGTH: usize = (64 * 1024 - 1) - UDP_HEADER - IP_HEADER;
const MAX_CHUNK_SIZE: usize = MAX_DATA_LENGTH - AG_HEADER;
const MAX_DATAGRAM_SIZE: usize = 0x10000;
/// A wrapper for [ptr::copy_nonoverlapping] with different argument order (same as original memcpy)
unsafe fn memcpy(dst_ptr: *mut u8, src_ptr: *const u8, len: usize) {
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, len);
}
// Different from https://doc.rust-lang.org/std/primitive.u32.html#method.next_power_of_two
// Returns the [exponent] from the smallest power of two greater than or equal to n.
const fn next_power_of_two_exponent(n: u32) -> u32 {
return 32 - (n - 1).leading_zeros();
}
async fn run_server(socket: UdpSocket) {
let mut missing_indexes: Vec<u16> = Vec::new();
let mut peer_addr = MaybeUninit::<SocketAddr>::uninit();
let mut data = std::ptr::null_mut(); // ptr for the file bytes
let mut len: usize = 0; // total len of bytes that will be written
let mut layout = MaybeUninit::<Layout>::uninit();
let mut buf = [0u8; MAX_DATA_LENGTH];
let mut start = false;
let (debounce_tx, mut debounce_rx) = mpsc::channel::<(usize, SocketAddr)>(3300);
let (network_tx, mut network_rx) = mpsc::channel::<(usize, SocketAddr)>(3300);
loop {
// Listen for events
let debouncer = task::spawn(async move {
let duration = Duration::from_millis(3300);
loop {
match time::timeout(duration, debounce_rx.recv()).await {
Ok(Some((size, peer))) => {
eprintln!("Network activity");
}
Ok(None) => {
if start == true {
eprintln!("Debounce finished");
break;
}
}
Err(_) => {
eprintln!("{:?} since network activity", duration);
}
}
}
});
// Listen for network activity
let server = task::spawn({
// async{
let debounce_tx = debounce_tx.clone();
async move {
while let Some((size, peer)) = network_rx.recv().await {
// Received a new packet
debounce_tx.send((size, peer)).await.expect("Unable to talk to debounce");
eprintln!("Received a packet {} from: {}", size, peer);
let packet_index: u16 = (buf[0] as u16) << 8 | buf[1] as u16;
if start == false { // first bytes of a new file: initialization // TODO: ADD A MUTEX to prevent many initializations
start = true;
let chunks_cnt: u32 = (buf[2] as u32) << 8 | buf[3] as u32;
let n: usize = MAX_DATAGRAM_SIZE << next_power_of_two_exponent(chunks_cnt);
unsafe {
layout.as_mut_ptr().write(Layout::from_size_align_unchecked(n, mem::align_of::<u8>()));
// /!\ data has type `*mut u8` which is not `Send`
data = alloc(layout.assume_init());
peer_addr.as_mut_ptr().write(peer);
}
let a: Vec<u16> = vec![0; chunks_cnt as usize]; //(0..chunks_cnt).map(|x| x as u16).collect(); // create a sorted vector with all the required indexes
missing_indexes = a;
}
missing_indexes[packet_index as usize] = 1;
unsafe {
let dst_ptr = data.offset((packet_index as usize * MAX_CHUNK_SIZE) as isize);
memcpy(dst_ptr, &buf[AG_HEADER], size - AG_HEADER);
};
println!("receiving packet {} from: {}", packet_index, peer);
}
}
});
// Prevent deadlocks
drop(debounce_tx);
match socket.recv_from(&mut buf).await {
Ok((size, src)) => {
network_tx.send((size, src)).await.expect("Unable to talk to network");
}
Err(e) => {
eprintln!("couldn't recieve a datagram: {}", e);
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let addr = env::args().nth(1).unwrap_or_else(|| "127.0.0.1:8080".to_string());
let socket = UdpSocket::bind(&addr).await?;
println!("Listening on: {}", socket.local_addr()?);
run_server(socket);
Ok(())
}
Since I was converting from synchronous to asynchronous code I know that, potentially, multiple thread would be writing to data, and that is probably why I encounter such error. But I don't know which syntax I could use to "clone" the mut ptr and make it unique for each thread (and same for the buffer).
As suggested by user4815162342 I think the best would be
to make pointer Send by wrapping it in a struct and declaring unsafe impl Send for NewStruct {}.
Any help strongly appreciated!
PS: Full code can be found on my github repository
Short version
Thanks to the comment of user4815162342 I decided to add an implementation for the mut ptr to be able to use it with Send and Sync, which allowed me to solve this part (there are still other issues, but beyond the scope of this question):
pub struct FileBuffer {
data: *mut u8
}
unsafe impl Send for FileBuffer {}
unsafe impl Sync for FileBuffer {}
//let mut data = std::ptr::null_mut(); // ptr for the file bytes
let mut fileBuffer: FileBuffer = FileBuffer { data: std::ptr::null_mut() };
Long version
use std::error::Error;
use std::time::Duration;
use std::env;
use tokio::net::UdpSocket;
use tokio::{sync::mpsc, task, time}; // 1.4.0
use std::alloc::{alloc, Layout};
use std::mem;
use std::mem::MaybeUninit;
use std::net::SocketAddr;
const UDP_HEADER: usize = 8;
const IP_HEADER: usize = 20;
const AG_HEADER: usize = 4;
const MAX_DATA_LENGTH: usize = (64 * 1024 - 1) - UDP_HEADER - IP_HEADER;
const MAX_CHUNK_SIZE: usize = MAX_DATA_LENGTH - AG_HEADER;
const MAX_DATAGRAM_SIZE: usize = 0x10000;
/// A wrapper for [ptr::copy_nonoverlapping] with different argument order (same as original memcpy)
unsafe fn memcpy(dst_ptr: *mut u8, src_ptr: *const u8, len: usize) {
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, len);
}
// Different from https://doc.rust-lang.org/std/primitive.u32.html#method.next_power_of_two
// Returns the [exponent] from the smallest power of two greater than or equal to n.
const fn next_power_of_two_exponent(n: u32) -> u32 {
return 32 - (n - 1).leading_zeros();
}
pub struct FileBuffer {
data: *mut u8
}
unsafe impl Send for FileBuffer {}
unsafe impl Sync for FileBuffer {}
async fn run_server(socket: UdpSocket) {
let mut missing_indexes: Vec<u16> = Vec::new();
let mut peer_addr = MaybeUninit::<SocketAddr>::uninit();
//let mut data = std::ptr::null_mut(); // ptr for the file bytes
let mut fileBuffer: FileBuffer = FileBuffer { data: std::ptr::null_mut() };
let mut len: usize = 0; // total len of bytes that will be written
let mut layout = MaybeUninit::<Layout>::uninit();
let mut buf = [0u8; MAX_DATA_LENGTH];
let mut start = false;
let (debounce_tx, mut debounce_rx) = mpsc::channel::<(usize, SocketAddr)>(3300);
let (network_tx, mut network_rx) = mpsc::channel::<(usize, SocketAddr)>(3300);
loop {
// Listen for events
let debouncer = task::spawn(async move {
let duration = Duration::from_millis(3300);
loop {
match time::timeout(duration, debounce_rx.recv()).await {
Ok(Some((size, peer))) => {
eprintln!("Network activity");
}
Ok(None) => {
if start == true {
eprintln!("Debounce finished");
break;
}
}
Err(_) => {
eprintln!("{:?} since network activity", duration);
}
}
}
});
// Listen for network activity
let server = task::spawn({
// async{
let debounce_tx = debounce_tx.clone();
async move {
while let Some((size, peer)) = network_rx.recv().await {
// Received a new packet
debounce_tx.send((size, peer)).await.expect("Unable to talk to debounce");
eprintln!("Received a packet {} from: {}", size, peer);
let packet_index: u16 = (buf[0] as u16) << 8 | buf[1] as u16;
if start == false { // first bytes of a new file: initialization // TODO: ADD A MUTEX to prevent many initializations
start = true;
let chunks_cnt: u32 = (buf[2] as u32) << 8 | buf[3] as u32;
let n: usize = MAX_DATAGRAM_SIZE << next_power_of_two_exponent(chunks_cnt);
unsafe {
layout.as_mut_ptr().write(Layout::from_size_align_unchecked(n, mem::align_of::<u8>()));
// /!\ data has type `*mut u8` which is not `Send`
fileBuffer.data = alloc(layout.assume_init());
peer_addr.as_mut_ptr().write(peer);
}
let a: Vec<u16> = vec![0; chunks_cnt as usize]; //(0..chunks_cnt).map(|x| x as u16).collect(); // create a sorted vector with all the required indexes
missing_indexes = a;
}
missing_indexes[packet_index as usize] = 1;
unsafe {
let dst_ptr = fileBuffer.data.offset((packet_index as usize * MAX_CHUNK_SIZE) as isize);
memcpy(dst_ptr, &buf[AG_HEADER], size - AG_HEADER);
};
println!("receiving packet {} from: {}", packet_index, peer);
}
}
});
// Prevent deadlocks
drop(debounce_tx);
match socket.recv_from(&mut buf).await {
Ok((size, src)) => {
network_tx.send((size, src)).await.expect("Unable to talk to network");
}
Err(e) => {
eprintln!("couldn't recieve a datagram: {}", e);
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let addr = env::args().nth(1).unwrap_or_else(|| "127.0.0.1:8080".to_string());
let socket = UdpSocket::bind(&addr).await?;
println!("Listening on: {}", socket.local_addr()?);
run_server(socket);
Ok(())
}
This question already has answers here:
How do I convert a Vector of bytes (u8) to a string?
(5 answers)
Closed 3 years ago.
I have a Vec<&[u8]> that I want to convert to a String like this:
let rfrce: Vec<&[u8]> = rec.alleles();
for r in rfrce {
// create new String from rfrce
}
I tried this but it is not working since only converting u8 to char is possible, but [u8] to char is not:
let rfrce = rec.alleles();
let mut str = String::from("");
for r in rfrce {
str.push(*r as char);
}
Because r is an array of u8, you need to convert it to a valid &str and use push_str method of String.
use std::str;
fn main() {
let rfrce = vec![&[65,66,67], &[68,69,70]];
let mut str = String::new();
for r in rfrce {
str.push_str(str::from_utf8(r).unwrap());
}
println!("{}", str);
}
Rust Playground
I'd go with TryFrom<u32>:
fn to_string(v: &[&[u8]]) -> Result<String, std::char::CharTryFromError> {
/// Transform a &[u8] to an UTF-8 codepoint
fn su8_to_u32(s: &[u8]) -> Option<u32> {
if s.len() > 4 {
None
} else {
let shift = (0..=32).step_by(8);
let result = s.iter().rev().cloned().zip(shift).map(|(u, shift)| (u as u32) << shift).sum();
Some(result)
}
}
use std::convert::TryFrom;
v.iter().map(|&s| su8_to_u32(s)).try_fold(String::new(), |mut s, u| {
let u = u.unwrap(); //TODO error handling
s.push(char::try_from(u)?);
Ok(s)
})
}
fn main() {
let rfrce: Vec<&[u8]> = vec![&[48][..], &[49][..], &[50][..], &[51][..]];
assert_eq!(to_string(&rfrce), Ok("0123".into()));
let rfrce: Vec<&[u8]> = vec![&[0xc3, 0xa9][..]]; // https://www.utf8icons.com/character/50089/utf-8-character
assert_eq!(to_string(&rfrce), Ok("쎩".into()));
}