Reputation: 109
I want to change a String into a vector of bytes and also modify its value, I have looked up and find How do I convert a string into a vector of bytes in rust?
but this can only get a reference and I cannot modify the vector. I want a
to be 0, b
to be 1 and so on, so after changing it into bytes I also need to subtract 97. Here is my attempt:
fn main() {
let s: String = "abcdefg".to_string();
let mut vec = (s.as_bytes()).clone();
println!("{:?}", vec);
for i in 0..vec.len() {
vec[i] -= 97;
}
println!("{:?}", vec);
}
but the compiler says
error[E0594]: cannot assign to `vec[_]`, which is behind a `&` reference
Can anyone help me to fix this?
Upvotes: 0
Views: 451
Reputation: 6657
You could get a Vec<u8>
out of the String
with the into_bytes
method. An even better way, though, may be to iterate over the String
's bytes with the bytes
method, do the maths on the fly, and then collect the result:
fn main() {
let s = "abcdefg";
let vec: Vec<u8> = s.bytes().map(|b| b - b'a').collect();
println!("{:?}", vec); // [0, 1, 2, 3, 4, 5, 6]
}
But as @SvenMarnach correctly points out, this won't re-use s
's buffer but allocate a new one. So, unless you need s
again, the into_bytes
method will be more efficient.
Upvotes: 4
Reputation: 8544
To understand what's going on, check the type of the vec
variable. If you don't have an IDE/editor that can display the type to you, you can do this:
let mut vec: () = (s.as_bytes()).clone();
The resulting error message is explanative:
3 | let mut vec: () = (s.as_bytes()).clone();
| -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&[u8]`
So, what's happening is that the .clone()
simply cloned the reference returned by as_bytes()
, and didn't create a Vec<u8>
from the &[u8]
. In general, you can use .to_owned()
in this kind of case, but in this specific case, using .into_bytes()
on the String
is best.
Upvotes: 3
Reputation: 602485
Strings in Rust are encoded in UTF-8. The (safe) interface of the String
type enforces that the underlying buffer always is valid UTF-8, so it can't allow direct arbitrary byte modifications. However, you can convert a String
into a Vec<u8>
using the into_bytes()
mehod. You can then modify the vector, and potentially convert it back to a string using String::from_utf8()
if desired. The last step will verify that the buffer still is vaid UTF-8, and will fail if it isn't.
Instead of modifying the bytes of the string, you could also consider modifying the characters, which are potentially encoded by multiple bytes in the UTF-8 encoding. You can iterate over the characters of the string using the chars()
method, convert each character to whatever you want, and then collect into a new string, or alternatively into a vector of integers, depending on your needs.
Upvotes: 3