How can I change the length of a vector in Rust? - vector

Editor's note: This question predates Rust 1.0 and syntax and methods have changed since then. Some answers account for Rust 1.0.
I have a function which I would like to have modify a vector in place.
fn f(v: &mut Vec<int>) {
v = Vec::from_elem(10 as uint, 0i);
}
fn main() {
let mut v: Vec<int> = Vec::new();
f(&mut v);
}
But this fails to compile. Specifically, I would like to resize v to contain 10 elements of value zero. What am I doing wrong?

Use the clear and resize methods. (This seems to be the right answer as of Rust 1.0 and 1.5, respectively.)
fn f(v: &mut Vec<u32>) {
// Remove all values in the vector
v.clear();
// Fill the vector with 10 zeros
v.resize(10, 0);
}
fn main() {
let mut v: Vec<u32> = Vec::new();
f(&mut v);
assert!(v == [0,0,0,0,0,0,0,0,0,0]);
}

Editor's note: This answer predates Rust 1.0 and is no longer necessarily accurate. Other answers still contain valuable information.
You're looking for the grow method.
let mut vec = vec![1i,2,3];
vec.grow(4, &10);
println!("{}", vec);
Or a combination of grow and clear.
You can browse the docs here: http://static.rust-lang.org/doc/master/std/vec/struct.Vec.html

Related

Rust: Convert a mutable u8 pointer to a mutable reference

How can I convert a mutable u8 pointer to a mutable reference of another type?
let ptr: *mut u8;
let reference: &mut SomeType = ?; // What should i do here?
I have found a sort-of viable solution, but I wonder if there is a better way:
let reference = unsafe { &mut *(ptr as *mut SomeType) };
You have already found an acceptable method. A slightly preferable one is to use pointer::cast instead of as, because that explicitly specifies that you are trying to change the type of the referent and not any of the many other things as can do.
let ptr = ptr.cast::<SomeType>();
let reference = unsafe { &mut *ptr };
Do not use std::mem::transmute for this. Transmuting should always be the last resort in any circumstance (the nomicon and function documentation say so!), because it reinterprets the bytes regardless of what they are — in this case it'll convert any pointer-sized value, such as a reference to the pointer. By sticking with cast and &*, we catch more possible type errors. (Clippy even has a default lint against using transmute here.)
You could use std::mem::transmute instead:
use std::mem::transmute;
#[repr(transparent)]
struct SomeStruct(u8);
fn main() {
let a = &mut 10u8;
let ptr = a as *mut u8;
let reference: &mut SomeStruct = unsafe { transmute(ptr) };
}

How to convert pointer to multidimensional slice/array

I'm writing a c-binding to a Rust function. The Rust function takes a 3D slice where 2 dimensions are of size two. Essentially it's a slice of 2D line segments where a line segment is represented by 2 points.
This means the segments have type:
segments: [[[f32; 2]; 2]]
Now since I call this from C I only have a simple f32 pointer at the FFI boundary. My multi-dimensional array from c is in row-major memory order which I understand matches what Rust would expect. So morally I should be able to say to rust: It's just that type.
I have looked at https://doc.rust-lang.org/std/ptr/fn.slice_from_raw_parts.html but I don't see how I can handle a more complex structure with that.
So to make it very concrete I want to be able to call foo from foo_c and foo should handle the conversion from pointer to the 3D slice/array structure.
#[no_mangle]
pub unsafe extern fn foo_c(segments: *f32, n_segments: usize) {
foo(...)
}
fn foo(segments: [[[f32; 2]; 2]]) {
...
}
If possible I would like to do this without copying any data around.
Any help is appreciated!
First I think you made some typos, so I'm assuming your code is:
#[no_mangle]
// missing `const`
pub unsafe extern fn foo_c(segments: *const f32, n_segments: usize) {
foo(...)
}
// missing `&`
fn foo(segments: &[[[f32; 2]; 2]]) {
...
}
The solution is:
#[no_mangle]
pub unsafe extern fn foo_c(segments: *const f32,n_segments: usize) {
// first we cast the pointer to get the slice `T`
// so from a generic `*const f32` to `*const T` where T is `[[f32; 2]; 2]`
let ptr = segments as *const [[f32; 2]; 2];
// we construct the slice using `slice_from_raw_parts`
// after we got the correct pointer.
let segments_slice = std::ptr::slice_from_raw_parts::<[[f32;2];2]>(ptr,n_segments);
// we still have `*const [[f32; 2]; 2]` which we need to convert
// to `&[[f32; 2]; 2]` so we use `&*` (dereference then borrow).
foo(&*segments_slice)
}
fn foo(segments: &[[[f32; 2]; 2]]) {
println!("segments {:?}",segments);
}

Does the key of a HashMap have to be a pointer in Rust?

I'm admittedly new to Rust. That being said, this doesn't make sense to me yet finding out why the behavior I'm seeing isn't what I expect seems like a good learning opportunity:
use std::iter::Enumerate;
use std::collections::HashMap;
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut numToI: HashMap<i32, usize> = HashMap::new();
for (i,v) in nums.iter().enumerate() {
let num: i32 = *v;
let complement: i32 = target - num;
if numToI.contains_key(complement) {
return vec![i as i32, numToI.get(complement) as i32];
} else {
numToI.insert(complement, i);
}
}
return vec![-1,-1];
}
}
Here I'm doing the simple question twoSum. I understand that nums.iter().enumerate() will return the values i and v, which are of type usize and a pointer to the element in nums (so in this case a reference to an i32), respectively. The thing I'm having trouble with is that although I specify numToI is a HashMap<i32, usize>, not HashMap<&i32, usize>, and I dereference to get the value of v with *v and assign the value to num, when I check if the HashMap numToI contains this i32 dereferenced value as a key, I get the error: expected &i32, found i32 on the call to contains_key. Why is this? Is it because the HashMap type always requires a pointer rather than a raw value, or is it due to an intricacy of Rust I'm not aware of? Shouldn't it expect a pointer for the key instead of a i32 if I had used HashMap<&i32, i32>?
More importantly, if this is due to a difference between Rust and C that has to do with the way borrowing etc. is used in Rust, where can I learn more about the intricacies of these differences?
contains_key takes a reference. It doesn't need to take ownership of the value to test with - it just needs to look at it temporarily.
Rust is complaining that you are passing in an i32 by value instead of a reference to it. It should tell you to borrow instead: numToI.contains_key(&complement).
That's the only issue with your code, really. HashMap keys don't need to be references, and it would be really inconvenient if they did.

Rust double ampersand, &&

I saw some code which looks like this:
fn test <'a> (&'a mut &'a str) {}
I know that 'a is a lifetime and that the & is a reference.
However I have trouble understanding a double reference &&.
In my understanding a reference is a pointer, so is a && a pointer to another pointer or something else?
In my understanding a reference is a pointer
Yes, a reference is just a pointer with special borrow-checking semantics. Pointers, and thus references, are just addresses in memory (and sometimes a size as well but that's irrelevant for this answer), which means that they essentially have a value of their own, separate from the value that they "point to" or "reference." That's why code like this can work:
fn main() {
let num1 = 1;
let num2 = 2;
let mut num_ref = &num1;
dbg!(num1, num2, num_ref); // num1 and num2 are 1 and 2 and num_ref is &1
num_ref = &num2;
dbg!(num1, num2, num_ref); // num1 and num2 are 1 and 2 and num_ref is &2
}
The values under the reference don't change, but the reference itself changes.
So, &mut &T is a mutable reference to an immutable reference, which means you can change the reference underneath the mutable reference:
fn make_reference_one(r: &mut &i32) {
*r = &1;
}
fn main() {
let mut num_ref = &2;
dbg!(num_ref); // is &2
make_reference_one(&mut num_ref);
dbg!(num_ref); // is now &1
}

How to allocate space for a Vec<T> in Rust?

I want to create a Vec<T> and make some room for it, but I don't know how to do it, and, to my surprise, there is almost nothing in the official documentation about this basic type.
let mut v: Vec<i32> = Vec<i32>(SIZE); // How do I do this ?
for i in 0..SIZE {
v[i] = i;
}
I know I can create an empty Vec<T> and fill it with pushes, but I don't want to do that since I don't always know, when writing a value at index i, if a value was already inserted there yet. I don't want to write, for obvious performance reasons, something like :
if i >= len(v) {
v.push(x);
} else {
v[i] = x;
}
And, of course, I can't use the vec! syntax either.
While vec![elem; count] from the accepted answer is sufficient to create a vector with all elements equal to the same value, there are other convenience functions.
Vec::with_capacity() creates a vector with the given capacity but with zero length. It means that until this capacity is reached, push() calls won't reallocate the vector, making push() essentially free:
fn main() {
let mut v = Vec::with_capacity(10);
for i in 0..10 {
v.push(i);
}
println!("{:?}", v);
}
You can also easily collect() a vector from an iterator. Example:
fn main() {
let v: Vec<_> = (1..10).collect();
println!("{:?}", v);
}
And finally, sometimes your vector contains values of primitive type and is supposed to be used as a buffer (e.g. in network communication). In this case you can use Vec::with_capacity() + set_len() unsafe method:
fn main() {
let mut v = Vec::with_capacity(10);
unsafe { v.set_len(10); }
for i in 0..10 {
v[i] = i;
}
println!("{:?}", v);
}
Note that you have to be extra careful if your vector contains values with destructors or references - it's easy to get a destructor run over a uninitialized piece of memory or to get an invalid reference this way. It will also work right if you only use initialized part of the vector (you have to track it yourself now). To read about all the possible dangers of uninitialized memory, you can read the documentation of mem::uninitialized().
You can use the first syntax of the vec! macro, specifically vec![elem; count]. For example:
vec![1; 10]
will create a Vec<_> containing 10 1s (the type _ will be determined later or default to i32). The elem given to the macro must implement Clone. The count can be a variable, too.
There is the Vec::resize method:
fn resize(&mut self, new_len: usize, value: T)
This code resizes an empty vector to 1024 elements by filling with the value 7:
let mut vec: Vec<i32> = Vec::new();
vec.resize(1024, 7);

Resources