Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to copy a slice from a raw pointer into a new slice ss:
pub fn receive(&mut self, data: *const u8, len: usize) {
let s = unsafe{slice::from_raw_parts(data, len)};
let mut ss = [0, len];
ss.copy_from_slice(s);
self.received.lock().unwrap().push_back(ss);
}
but I'm having trouble creating this new slice. I tried to give the lenght len so it's compatible with slice s but I do not understand what's happening
I'm trying to copy a slice from a raw pointer into a new slice ss:
There is no such thing as a "new slice", a slice always points to memory from something else. If you want to copy an existing slice to a new location, you will need to allocate the data for that location, e.g. using a Vec:
let mut ss = vec![0; len];
ss.copy_from_slice(s);
However, since you already have a slice (s) and the push_back method of self.received accepts a slice, why not avoid the copying and simply call self.received.lock().unwrap().push_back(s)?
Providing error messages is usually helpful to help diagnose issues. Providing an immediately usable reproduction of the issue (e.g. something on the playground) is also useful.
Anyway cutting down on the things we can't know and don't care about in your function we get this:
use std::slice;
fn receive(data: *const u8, len: usize) {
let s = unsafe{slice::from_raw_parts(data, len)};
let mut ss = [0, len];
ss.copy_from_slice(s);
}
Compiling yields the following:
error[E0308]: mismatched types
--> src/lib.rs:6:28
|
6 | ss.copy_from_slice(s);
| ^ expected `usize`, found `u8`
|
= note: expected reference `&[usize]`
found reference `&[u8]`
So ss is a &[usize] instead of an &[u8]. Weird. Let's explicitly type ss as an &[u8] to try and force it then:
error[E0308]: mismatched types
--> src/lib.rs:5:25
|
5 | let mut ss: &[u8] = [0, len];
| ----- ^^^^^^^^ expected `&[u8]`, found array `[usize; 2]`
| |
| expected due to this
Well there's the issue: [0, len] is not a slice. It's an array of length 2 containing the two elements 0 and whatever len is (and since len is usize it's an [usize;2]. A slice literal is &[], and neither arrays nor slice literals can take a runtime length, the length needs to be known at compile-time.
And even if you do make it a slice, you probably won't be able to push it into received, because the slice just refers to data local to the function, it won't be able to escape.
You might want a Vec.
Related
I am trying to print some data for debugging purposes when I encountered an error. You can have a look at the full code here.
The error occurred when I tried to print data returned from the prepare_hash_data() function, which returns a Vec<u8>.
let data = self.prepare_hash_data()?; // returns Vec<u8>
println!("{}", String::from_utf8(data)?); // error here
let mut hasher = Sha256::new();
hasher.input(&data[..]);
println!("{}", hasher.result_str().as_str());
self.hash = hasher.result_str();
The prepare_hash_data() function is given below. Other details are omitted. Simply, it is just a function that returns Vec<u8>
fn prepare_hash_data(&self) -> Result<Vec<u8>, failure::Error> {
let content = (
self.hash_prev_block.clone(),
self.transactions.clone(),
self.timestamp,
DIFFICULTY,
self.nonce
);
let bytes = bincode::serialize(&content)?;
Ok(bytes)
}
The error given is
error[E0382]: borrow of moved value: `data`
--> src/block.rs:63:23
|
60 | let data = self.prepare_hash_data()?;
| ---- move occurs because `data` has type `Vec<u8>`, which does not implement the `Copy` trait
61 | println!("{}", String::from_utf8(data)?);
| ---- value moved here
62 | let mut hasher = Sha256::new();
63 | hasher.input(&data[..]);
| ^^^^ value borrowed here after move
I tried the following ways
Implementing Copy trait. But, Vec<u8> can't have the Copy trait as described here.
Looking at E0382 given in the error message, there are two ways suggested.
Using a reference, we can let another function borrow the value without changing its ownership.
But how should I use reference in this example?
Should I change the function signature to something like this fn prepare_hash_data(&self) -> Result<&Vec<u8>, failure::Error>?
With Rc, a value cannot be owned by more than one variable.
Don't know how to implement.
I tried cloning the data by println!("{}", String::from_utf8(data.clone())?);
But, it gives another error backtrace::backtrace::trace_unsynchronized
For the full error log, click here
What should be the correct approach to printing some data that can't be copied or cloned without moving it for later usage in subsequent lines?
I did look at the following solutions but can't relate the answer.
move occurs because value has type Vec, which does not implement the Copy trait
'move occurs because value has type' Rust error
I am trying to print some data for debugging purposes
The code you provided:
println!("{}", String::from_utf8(data)?);
Is not the correct way to debug-print data.
For one, String::from_utf8 consumes the data, destroying it in the process. Further, your data most likely isn't valid UTF8 data, so String::from_utf8 will only throw an error.
Use debug printing instead, it works out of the box:
println!("{:?}, data);
I retract my previous answer because it partially missed your problem.
It still contained valuable information, so I have kept it below. If someone disagrees, feel free to delete it together with this sentence.
--Previous Answer--
Your problem is that String::from_utf8 consumes its argument, meaning, data cannot be accessed any more afterwards.
Here is your problem in a more compact example:
fn main() {
let data: Vec<u8> = "Hello!".as_bytes().to_vec();
// Consumes `data`
println!("{}", String::from_utf8(data).unwrap());
// `data` cannot be accessed any more, as it got moved
// into `String::from_utf8`
println!("Length of vector: {}", data.len());
}
error[E0382]: borrow of moved value: `data`
--> src/main.rs:9:38
|
2 | let data: Vec<u8> = "Hello!".as_bytes().to_vec();
| ---- move occurs because `data` has type `Vec<u8>`, which does not implement the `Copy` trait
...
5 | println!("{}", String::from_utf8(data).unwrap());
| ---- value moved here
...
9 | println!("Length of vector: {}", data.len());
| ^^^^^^^^^^ value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
5 | println!("{}", String::from_utf8(data.clone()).unwrap());
| ++++++++
In your case this can be easily fixed, though. The reason it consumes the data is because String is an owning variable. It owns its data, meaning, if you create it from a Vec, it stores the Vec data internally.
There is another type: &str, a string slice. It's very similar to String, just that it doesn't own its data, but merely references it. That means you can create it without destroying data:
fn main() {
let data: Vec<u8> = "Hello!".as_bytes().to_vec();
// Borrows `data`
println!("{}", std::str::from_utf8(&data).unwrap());
// `data` is still accessible because it was only borrowed
println!("Length of vector: {}", data.len());
}
Hello!
Length of vector: 6
That said, the given solution is only a workaround. The proper way to fix this is to implement Display.
As your data object clearly has more meaning than just a bunch of bytes, create a proper struct that represents its meaning.
There are two ways I would consider:
A newtype struct, like struct MyData(Vec<u8>), for which you can implement Display.
A String. As you convert it to a string anyway, why not just make it a string right away, as the return value of prepare_hash_data? Note that if your reason to have it a Vec is that it is binary data, then you shouldn't convert it to a string via from_utf8, as it's not UTF-8 data. If it is valid UTF-8 data, however, use a String right away, not a Vec<u8>. And String already implements Display and can be printed without further conversion.
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 last month.
Improve this question
I want to print out every value from this vector and I know I can do it with .enumerate, but I'm curious what's wrong with this:
fn main() {
let vec = vec![1,2,3];
for i in vec.iter() {
println!("{}", vec[i as usize]);
}
}
I'm new to Rust, so go easy on me.
Here's the error I got from the faulty code:
error[E0277]: the type `[{integer}]` cannot be indexed by `&{integer}`
--> src\main.rs:4:24
|
4 | println!("{}", vec[i]);
| ^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `&{integer}`
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
= note: required because of the requirements on the impl of `Index<&{integer}>` for `Vec<{integer}>`
For more information about this error, try `rustc --explain E0277`.
i is the item being iterated and not the iterator itself.
(Like you said) You can use enumerate to get the iterator index variable, and that is the right way if you want to retrieve the usize index of the vector.
for (i,n) in vec.iter().enumerate()
You don’t need to index your vector in this case. for yields an element every iteration.
let v = vec![1, 2, 3];
for i in v {
println!("{i}");
}
prints
1
2
3
Vec::iter produces an iterator over references to elements (&something). In order to cast a reference to usize or use a reference as an index, you have to dereference it somehow; one way is exactly as the error message that you didn’t post suggests, using the dereferencing operator *.
let vec = vec![1,2,3];
for i in vec.iter() {
println!("{}", vec[*i as usize]);
}
(It’s also possible to leave out the as usize cast, and the type of vec will be inferred as Vec<usize>.)
Then you run into the issue that vec[3] doesn’t exist. If you just wanted to print the contents of the vector, there’s no need to index into vec; .iter() is already an iterator over the elements, not indices, of a vector.
let vec = vec![1, 2, 3];
for &i in vec.iter() {
println!("{}", i);
}
(This is also an example of a different way to dereference, by using a reference pattern &i, and you can write for &i in &vec, too. Or for i in vec directly if you don’t need vec afterwards, which works on non-copyable types.)
This question already has answers here:
How do I convert a Vec<T> to a Vec<U> without copying the vector?
(2 answers)
Closed 3 years ago.
Is there a better way to cast Vec<i8> to Vec<u8> in Rust except for these two?
creating a copy by mapping and casting every entry
using std::transmute
The (1) is slow, the (2) is "transmute should be the absolute last resort" according to the docs.
A bit of background maybe: I'm getting a Vec<i8> from the unsafe gl::GetShaderInfoLog() call and want to create a string from this vector of chars by using String::from_utf8().
The other answers provide excellent solutions for the underlying problem of creating a string from Vec<i8>. To answer the question as posed, creating a Vec<u8> from data in a Vec<i8> can be done without copying or transmuting the vector. As pointed out by #trentcl, transmuting the vector directly constitutes undefined behavior because Vec is allowed to have different layout for different types.
The correct (though still requiring the use of unsafe) way to transfer a vector's data without copying it is:
obtain the *mut i8 pointer to the data in the vector, along with its length and capacity
leak the original vector to prevent it from freeing the data
use Vec::from_raw_parts to build a new vector, giving it the pointer cast to *mut u8 - this is the unsafe part, because we are vouching that the pointer contains valid and initialized data, and that it is not in use by other objects, and so on.
This is not UB because the new Vec is given the pointer of the correct type from the start. Code (playground):
fn vec_i8_into_u8(v: Vec<i8>) -> Vec<u8> {
// ideally we'd use Vec::into_raw_parts, but it's unstable,
// so we have to do it manually:
// first, make sure v's destructor doesn't free the data
// it thinks it owns when it goes out of scope
let mut v = std::mem::ManuallyDrop::new(v);
// then, pick apart the existing Vec
let p = v.as_mut_ptr();
let len = v.len();
let cap = v.capacity();
// finally, adopt the data into a new Vec
unsafe { Vec::from_raw_parts(p as *mut u8, len, cap) }
}
fn main() {
let v = vec![-1i8, 2, 3];
assert!(vec_i8_into_u8(v) == vec![255u8, 2, 3]);
}
transmute on a Vec is always, 100% wrong, causing undefined behavior, because the layout of Vec is not specified. However, as the page you linked also mentions, you can use raw pointers and Vec::from_raw_parts to perform this correctly. user4815162342's answer shows how.
(std::mem::transmute is the only item in the Rust standard library whose documentation consists mostly of suggestions for how not to use it. Take that how you will.)
However, in this case, from_raw_parts is also unnecessary. The best way to deal with C strings in Rust is with the wrappers in std::ffi, CStr and CString. There may be better ways to work this in to your real code, but here's one way you could use CStr to borrow a Vec<c_char> as a &str:
const BUF_SIZE: usize = 1000;
let mut info_log: Vec<c_char> = vec![0; BUF_SIZE];
let mut len: usize;
unsafe {
gl::GetShaderInfoLog(shader, BUF_SIZE, &mut len, info_log.as_mut_ptr());
}
let log = Cstr::from_bytes_with_nul(info_log[..len + 1])
.expect("Slice must be nul terminated and contain no nul bytes")
.to_str()
.expect("Slice must be valid UTF-8 text");
Notice there is no unsafe code except to call the FFI function; you could also use with_capacity + set_len (as in wasmup's answer) to skip initializing the Vec to 1000 zeros, and use from_bytes_with_nul_unchecked to skip checking the validity of the returned string.
See this:
fn get_compilation_log(&self) -> String {
let mut len = 0;
unsafe { gl::GetShaderiv(self.id, gl::INFO_LOG_LENGTH, &mut len) };
assert!(len > 0);
let mut buf = Vec::with_capacity(len as usize);
let buf_ptr = buf.as_mut_ptr() as *mut gl::types::GLchar;
unsafe {
gl::GetShaderInfoLog(self.id, len, std::ptr::null_mut(), buf_ptr);
buf.set_len(len as usize);
};
match String::from_utf8(buf) {
Ok(log) => log,
Err(vec) => panic!("Could not convert compilation log from buffer: {}", vec),
}
}
See ffi:
let s = CStr::from_ptr(strz_ptr).to_str().unwrap();
Doc
I'm attempting to simply convert a slice to a vector. The following code:
let a = &[0u8];
let b: Vec<u8> = a.iter().collect();
fails with the following error message:
3 | let b: Vec<u8> = a.iter().collect();
| ^^^^^^^ a collection of type `std::vec::Vec<u8>` cannot be built from an iterator over elements of type `&u8`
What am I missing?
Collecting into a Vec is so common that slices have a method to_vec that does exactly this:
let b = a.to_vec();
You get the same thing as CodesInChaos's answer, but more concisely.
Notice that to_vec requires T: Clone. To get a Vec<T> out of a &[T] you have to be able to get an owned T out of a non-owning &T, which is what Clone does.
Slices also implement ToOwned, so you can use to_owned instead of to_vec if you want to be generic over different types of non-owning container. If your code only works with slices, prefer to_vec instead.
The iterator only returns references to the elements (here &u8). To get owned values (here u8), you can used .cloned().
let a: &[u8] = &[0u8];
let b: Vec<u8> = a.iter().cloned().collect();
How can I create an empty [u8] that I can then pass to an openssl function so it can write it's result to it?
fn test_encrypt(key_pair: openssl::rsa::Rsa) {
let text = b"Hello";
println!("{:?}", text);
let mut result = b" ";
let pad = openssl::rsa::Padding::from_raw(1);
key_pair.private_encrypt(text, result, pad);
}
My code currently results in the following error:
error[E0308]: mismatched types
--> src/main.rs:20:36
|
20 | key_pair.private_encrypt(text, result, pad);
| ^^^^^^ types differ in mutability
|
= note: expected type `&mut [u8]`
found type `&[u8; 0]`
Reading the error messages will help you far more; mismatched types, types differ in mutability, expected type &mut [u8], found type &[u8; 0]. You problem isn't how to create an array, it's that you aren't creating the right type of array.
Printing the type of the variable will show that b" " creates a &[u8; 1] — an immutable reference to an array. It doesn't matter what you try, you won't be able to write into this data. In fact, it's stored in the static data in the compiled executable.
Instead, you need something that can be used as a mutable slice. The two primary ways are to create an actual array or a Vec:
// Array
let mut result = [0; 24];
key_pair.private_encrypt(text, &mut result, pad);
// Vec
let mut result = vec![0; 24];
key_pair.private_encrypt(text, &mut result, pad);
An array is stack-allocated and has a fixed size and capacity which must be equal. A vector is heap-allocated, has a dynamic size and capacity that may differ from each other.
Both of these can be dereferenced to a &mut [u8].
Picking the appropriate size for your array or vector is something that is application specific. Checking the OpenSSL documentation is the right course of action.
The private_encrypt() method expects a mutable slice of a sufficiently long buffer (key_pair.size() bytes). Change
let mut result = b" ";
key_pair.private_encrypt(text, result, pad);
to
let mut result = vec![0; key_pair.size()];
key_pair.private_encrypt(text, &mut result, pad);