How to convert u8 to &[u8] in Rust? [duplicate] - rust

This question already has answers here:
Converting number primitives (i32, f64, etc) to byte representations
(5 answers)
Closed 3 years ago.
I am new and lost in Rust a bit.
I would like to add keys and values to a data store that has a put function that takes two byte string literals:
batch.put(b"foxi", b"maxi");
I generate a bunch of these k-v pairs:
for _ in 1..1000000 {
let mut ivec = Vec::new();
let s1: u8 = rng.gen();
let s2: u8 = rng.gen();
ivec.push(s1);
ivec.push(s2);
debug!("Adding key: {} and value {}", s1, s2);
vec.push(ivec);
}
let _ = database::write(db, vec);
I have a fn that tries to add them:
pub fn write(db: DB, vec: Vec<Vec<u8>>) {
let batch = WriteBatch::new();
for v in vec {
batch.put(v[0], v[1]);
}
db.write(&batch).unwrap();
}
When I try to compile this I get:
error[E0308]: mismatched types
--> src/database.rs:17:19
|
17 | batch.put(v[0], v[1]);
| ^^^^ expected &[u8], found u8
|
= note: expected type `&[u8]`
found type `u8`
error[E0308]: mismatched types
--> src/database.rs:17:25
|
17 | batch.put(v[0], v[1]);
| ^^^^ expected &[u8], found u8
|
= note: expected type `&[u8]`
found type `u8`
I was ping-ponging with the borrow checker for a while now but I could not get it working. What is the best way to have byte literal strings from u8s?

The following works:
batch.put(&v[0].as_bytes(), &v[1].as_bytes())

Related

Error with non matching type: Option<&[u8]> and Option<&[u8;32]>

I playing with the Rust code, and I've got to a place in which I have a problem with converting Option<&[u8; 32]> to Option<&[u8]>.
A (very) simplified example:
pub type Foo = [u8; 32];
fn fun_one(inp: Option<&[u8]>) {
println!("{:?}", inp);
}
fn fun_two(x: Option<&Foo>) {
fun_one(x)
}
fn main() {
let x = [11u8; 32];
fun_two(Some(&x));
}
Link: Rust Playground
error[E0308]: mismatched types
--> src/main.rs:8:13
|
8 | fun_one(x)
| ^ expected slice `[u8]`, found array `[u8; 32]`
|
= note: expected enum `Option<&[u8]>`
found enum `Option<&[u8; 32]>`
A slice isn't just a pointer over an array. It's both the pointer to the data and a length (see Arrays and Slices) as it refers to only a part of the array. This is why the types aren't compatible.
What you want here is a slice over the whole array, which you get with the .. full range expression: slice = &array[..].
Having an option, you can conditionnaly apply this transformation using map.
Combining all this:
fn fun_two(x: Option<&Foo>) {
fun_one(x.map(|a| &a[..]))
}

Why can't std::iter::Map<I, F> be returned as Iterator<Item = I>? [duplicate]

This question already has answers here:
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
"Expected type parameter" error in the constructor of a generic struct
(1 answer)
Closed 2 years ago.
I want make the mapping portion of this line into a function:
let i: Vec<u32> = (0..=5).map(|x| x * 2).collect();
I wrote this code which I assumed would be a drop-in for what I removed from the original code:
let j: Vec<u32> = process(0..=5).collect();
fn process<I>(src: I) -> I
where
I: Iterator<Item = u32>,
{
src.map(|x| x * 2)
}
I get this compile time error:
error[E0308]: mismatched types
--> src/lib.rs:5:5
|
1 | fn process<I>(src: I) -> I
| - - expected `I` because of return type
| |
| this type parameter
...
5 | src.map(|x| x * 2)
| ^^^^^^^^^^^^^^^^^^ expected type parameter `I`, found struct `std::iter::Map`
|
= note: expected type parameter `I`
found struct `std::iter::Map<I, [closure#src/lib.rs:5:13: 5:22]>`
Playground
Since std::iter::Map<u32, u32> implements the Iterator trait, shouldn't it be able to be returned as Iterator<Item = u32>?
I was able to get it working with the following:
fn process<I>(src: I) -> std::iter::Map<I, Box<dyn Fn(u32) -> u32>>
where
I: Iterator<Item = u32>,
{
src.map(Box::new(|x| x * 2))
}
This involves wrapping the closure in a Box. Is there a better or less verbose way to do this that matches the inline function?

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.

Rust doesn't have a size known at compile-time [duplicate]

This question already has answers here:
What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?
(1 answer)
Return local String as a slice (&str)
(7 answers)
Proper way to return a new string in Rust
(2 answers)
Closed 3 years ago.
I am having problems in an exercise where I try to get an impl block to return the value of the i32 in the struct in str format. I don't know if it is doing well or if it is possible to do this, this is the complete error:
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:6:20
|
6 | fn x(&self) -> str {
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
--> src/main.rs:9:9
|
6 | fn x(&self) -> str {
| --- expected `str` because of return type
...
9 | *_newword
| ^^^^^^^^^ expected `str`, found struct `std::string::String`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:17:5
|
17 | println!("x is: {}", f.x());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
This is the code that I am trying to make work:
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn x(&self) -> str {
let word = *self.x;
let _newword = &word.to_string();
*_newword
}
}
fn main() {
let y = &5;
let f = Foo { x: y };
println!("x is: {}", f.x());
}

How do I convert a Vec<MyStruct> to a Vec<String> then to a Vec<&str> in a single step? [duplicate]

This question already has answers here:
Return local String as a slice (&str)
(7 answers)
Is there any way to return a reference to a variable created in a function?
(5 answers)
How do I convert a Vec<String> to Vec<&str>?
(6 answers)
Closed 3 years ago.
I am trying to convert a Vec of a given struct to its String and eventually to &str format.
This example code simulates exactly what I am trying to achieve.
fn main() {
let a = vec![1i32, 2i32, 3i32];
let step1: Vec<String> = a.iter().map(|x| x.to_string()).collect::<Vec<String>>();
let step2: Vec<&str> = step1.iter().map(AsRef::as_ref).collect::<Vec<&str>>();
// This does not work as I was expecting it to
// and its not being accepted by the compiler as valid code
//
let in_single_step: Vec<&str> = a
.iter()
.map(|x| x.to_string()) // <--- Something is needed after this step?
.map(AsRef::as_ref)
.collect::<Vec<&str>>();
println!("{:?}", in_single_step);
}
playground with this code
I get an error:
error[E0631]: type mismatch in function arguments
--> src/main.rs:14:10
|
14 | .map(AsRef::as_ref)
| ^^^
| |
| expected signature of `fn(std::string::String) -> _`
| found signature of `for<'r> fn(&'r _) -> _`
error[E0599]: no method named `collect` found for type `std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure#src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}>` in the current scope
--> src/main.rs:15:10
|
15 | .collect::<Vec<&str>>();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`&mut std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure#src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}> : std::iter::Iterator`
`std::iter::Map<std::iter::Map<std::slice::Iter<'_, i32>, [closure#src/main.rs:13:14: 13:31]>, for<'r> fn(&'r _) -> &'r _ {<_ as std::convert::AsRef<_>>::as_ref}> : std::iter::Iterator`
Similar questions are:
Convert Vec<String> to Vec<&str>
Convert Vec<String> into a slice of &str in Rust?

Resources