How do I create an empty byte array? - rust

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);

Related

can't cast slices indices into u8 type to be inserted in a macro expecting expression [duplicate]

I have a 2D vector in Rust which I am trying to index with a dynamic u8 variable. An example of what I'm trying to do is below:
fn main() {
let mut vec2d: Vec<Vec<u8>> = Vec::new();
let row: u8 = 1;
let col: u8 = 2;
for i in 0..4 {
let mut rowVec: Vec<u8> = Vec::new();
for j in 0..4 {
rowVec.push(j as u8);
}
vec2d.push(rowVec);
}
println!("{}", vec2d[row][col]);
}
However, I get the error
error: the trait `core::ops::Index<u8>` is not implemented for the type `collections::vec::Vec<collections::vec::Vec<u8>>` [E0277]
In later versions of Rust, I get
error[E0277]: the trait bound `u8: std::slice::SliceIndex<[std::vec::Vec<u8>]>` is not satisfied
--> src/main.rs:15:20
|
15 | println!("{}", vec2d[row][col]);
| ^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::vec::Vec<u8>]>` is not implemented for `u8`
= note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<std::vec::Vec<u8>>`
What must I cast the u8 to in able to use it as an index in my vector?
Indices are of type usize; usize is used for sizes of collections, or indices into collections. It represents the native pointer size on your architecture.
This is what you need to use for this to work properly:
println!("{}", vec2d[usize::from(row)][usize::from(col)]);
You should cast it as a usize, which I find more readable than
of your_vector[index_u8] use your_vector[index_u8 as usize]
I personally find x as usize to be more readable than usize::from(x), but this is just my preference.
In your case:
println!(“{}”, vec2d[row as usize][col as usize]);
This occurs because v[i] is really parsed as *(&v + i), or the value at (the memory address of the vector + the index). Because &v is a memory address, i, the index, must also be a memory address type. Rust represents memory addresses of the type usize.
I know this has already been answered but I just prefer x as usize to usize::from(x). The decision is yours.

swapping two entries of a HashMap

i have a simple HashMap; say HashMap<char, char>.
is there a way to swap two elements in this hashmap using std::mem::swap (or any other method)?
Of course there is the simple way getting the values with get and then replace them with insert - but that would trigger the hasher twice (once for getting then for inserting) and i was looking for a way to side-step the second hasher invocation (more out of curiosity than for performance).
what i tried is this (in several versions; none of which worked - and as remarked in the comments: entry would not do what i expect even if i got this past the compiler):
use std::collections::HashMap;
use std::mem::swap;
let mut hash_map: HashMap<char, char> = HashMap::default();
hash_map.insert('A', 'Z');
hash_map.insert('B', 'Y');
swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
now the compiler complains (an i understand why it should)
error[E0499]: cannot borrow `hash_map` as mutable more than once at a time
--> tests.rs:103:42
|
103 | swap(&mut hash_map.entry('A'), &mut hash_map.entry('B'));
| ---- -------- ^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
also just getting the two values this way fails in more or less the same way:
let mut a_val = hash_map.get_mut(&'A').expect("failed to get A value");
let mut b_val = hash_map.get_mut(&'B').expect("failed to get B value");
swap(&mut a_val, &mut b_val);
is there a way to simply swap two entries of a HashMap?
I can't see any safe way to do it:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert('A', 'Z');
map.insert('B', 'Y');
let a = map.get_mut(&'A').unwrap() as *mut char;
let b = map.get_mut(&'B').unwrap() as *mut char;
unsafe {
std::ptr::swap(a, b);
}
assert_eq!(map.get(&'A'), Some(&'Y'));
assert_eq!(map.get(&'B'), Some(&'Z'));
}
There is one completely safe way I can think of to do this safely, but it's super inefficient: what you want is to get two &mut values, which means borrowck needs to know they're nonoverlapping. Missing a builtin along the lines of split_mut (or the collection being handled specially), the only way I see is to mutably iterate the entire collection, keep refs to the items you're interested in, and swap that:
let mut h = HashMap::new();
h.insert("a", "a");
h.insert("b", "b");
let mut it = h.iter_mut();
let e0 = it.next().unwrap();
let e1 = it.next().unwrap();
std::mem::swap(e0.1, e1.1);
println!("{:?}", h);
It requires a linear traversal of the map until you've found the entries whose values you want to swap though. So even though this has the advantage of not hashing at all edwardw's is answer is probably more practical.

Finding most frequently occurring string in a structure in Rust?

I'm looking for the string which occurs most frequently in the second part of the tuple of Vec<(String, Vec<String>)>:
use itertools::Itertools; // 0.8.0
fn main() {
let edges: Vec<(String, Vec<String>)> = vec![];
let x = edges
.iter()
.flat_map(|x| &x.1)
.map(|x| &x[..])
.sorted()
.group_by(|x| x)
.max_by_key(|x| x.len());
}
Playground
This:
takes the iterator
flat-maps to the second part of the tuple
turns elements into a &str
sorts it (via itertools)
groups it by string (via itertools)
find the group with the highest count
This supposedly gives me the group with the most frequently occurring string, except it doesn't compile:
error[E0599]: no method named `max_by_key` found for type `itertools::groupbylazy::GroupBy<&&str, std::vec::IntoIter<&str>, [closure#src/lib.rs:9:19: 9:24]>` in the current scope
--> src/lib.rs:10:10
|
10 | .max_by_key(|x| x.len());
| ^^^^^^^^^^
|
= note: the method `max_by_key` exists but the following trait bounds were not satisfied:
`&mut itertools::groupbylazy::GroupBy<&&str, std::vec::IntoIter<&str>, [closure#src/lib.rs:9:19: 9:24]> : std::iter::Iterator`
I'm totally lost in these types.
You didn't read the documentation for a function you are using. This is not a good idea.
This type implements IntoIterator (it is not an iterator itself),
because the group iterators need to borrow from this value. It should
be stored in a local variable or temporary and iterated.
Personally, I'd just use a BTreeMap or HashMap:
let mut counts = BTreeMap::new();
for word in edges.iter().flat_map(|x| &x.1) {
*counts.entry(word).or_insert(0) += 1;
}
let max = counts.into_iter().max_by_key(|&(_, count)| count);
println!("{:?}", max);
If you really wanted to use the iterators, it could look something like this:
let groups = edges
.iter()
.flat_map(|x| &x.1)
.sorted()
.group_by(|&x| x);
let max = groups
.into_iter()
.map(|(key, group)| (key, group.count()))
.max_by_key(|&(_, count)| count);

How to convert from &[u8] to Vec<u8>?

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

What must I cast an `u8` to in able to use it as an index in my vector?

I have a 2D vector in Rust which I am trying to index with a dynamic u8 variable. An example of what I'm trying to do is below:
fn main() {
let mut vec2d: Vec<Vec<u8>> = Vec::new();
let row: u8 = 1;
let col: u8 = 2;
for i in 0..4 {
let mut rowVec: Vec<u8> = Vec::new();
for j in 0..4 {
rowVec.push(j as u8);
}
vec2d.push(rowVec);
}
println!("{}", vec2d[row][col]);
}
However, I get the error
error: the trait `core::ops::Index<u8>` is not implemented for the type `collections::vec::Vec<collections::vec::Vec<u8>>` [E0277]
In later versions of Rust, I get
error[E0277]: the trait bound `u8: std::slice::SliceIndex<[std::vec::Vec<u8>]>` is not satisfied
--> src/main.rs:15:20
|
15 | println!("{}", vec2d[row][col]);
| ^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::vec::Vec<u8>]>` is not implemented for `u8`
= note: required because of the requirements on the impl of `std::ops::Index<u8>` for `std::vec::Vec<std::vec::Vec<u8>>`
What must I cast the u8 to in able to use it as an index in my vector?
Indices are of type usize; usize is used for sizes of collections, or indices into collections. It represents the native pointer size on your architecture.
This is what you need to use for this to work properly:
println!("{}", vec2d[usize::from(row)][usize::from(col)]);
You should cast it as a usize, which I find more readable than
of your_vector[index_u8] use your_vector[index_u8 as usize]
I personally find x as usize to be more readable than usize::from(x), but this is just my preference.
In your case:
println!(“{}”, vec2d[row as usize][col as usize]);
This occurs because v[i] is really parsed as *(&v + i), or the value at (the memory address of the vector + the index). Because &v is a memory address, i, the index, must also be a memory address type. Rust represents memory addresses of the type usize.
I know this has already been answered but I just prefer x as usize to usize::from(x). The decision is yours.

Resources