Your code example is not very complete. The part that actually causes the error can't be seen in your example.
I guess that your code looks something like this:
pub fn function1(s: String) -> i32 {
let index: &i32 = &1;
let substring = (&s[index..]).to_string();
let counter = function1(substring);
10
}
error[E0277]: the type `String` cannot be indexed by `RangeFrom<&i32>`
--> src/main.rs:3:23
|
3 | let substring = (&s[index..]).to_string();
| ^^^^^^^^^^ `String` cannot be indexed by `RangeFrom<&i32>`
|
= help: the trait `Index<RangeFrom<&i32>>` is not implemented for `String`
Problems
indexmust be ausize, but it is an&i32. This is the main error that you see.- You cannot slice a string directly, you need to convert from char-based indices to byte-based indices first. This can be done by iterating through
char_indices().
Here is a rough sketch of how this might look like:
pub fn function1(s: String) -> i32 {
println!("s: {}", s);
let index: &i32 = &1;
// Try to convert the index to a byte position
let substring = match s.char_indices().nth(*index as usize) {
// If a position with the given index was found in the string, create a substring
Some((pos, _)) => (&s[pos..]).to_string(),
// Else, create an empty string
None => "".to_string(),
};
// Break if the substring is empty, otherwise we would have an infinite recursion
if substring.is_empty() {
return 0;
}
let counter = function1(substring);
counter + 1
}
fn main() {
let input_str = "ππππ€ͺ".to_string();
let result = function1(input_str);
println!("Result: {}", result);
}
s: ππππ€ͺ
s: πππ€ͺ
s: ππ€ͺ
s: π€ͺ
Result: 3
Slicing vs copying
With every iteration of your function, you are creating a new copy of the string. This is quite slow, and I don't see a reason why this would be necessary in your case.
What you really want is a slice of the input string. This doesn't copy any data, it simply references a part of the original string.
To achieve that, you would have to change your parameter type from String to &str. There is no reason your function would need to take ownership. Even if you want to take ownership, then to_string() would do so, as it creates a copy of the data. So there really is no reason to use String as the parameter type.
pub fn function1(s: &str) -> i32 {
println!("s: {}", s);
let index: &i32 = &1;
// Try to convert the index to a byte position
let substring = match s.char_indices().nth(*index as usize) {
// If a position with the given index was found in the string, create a substring slice
Some((pos, _)) => &s[pos..],
// Else, use an empty string
None => "",
};
// Break if the substring is empty, otherwise we would have an infinite recursion
if substring.is_empty() {
return 0;
}
let counter = function1(substring);
counter + 1
}
fn main() {
let input_str = "ππππ€ͺ".to_string();
let result = function1(&input_str);
println!("Result: {}", result);
}
s: ππππ€ͺ
s: πππ€ͺ
s: ππ€ͺ
s: π€ͺ
Result: 3
Answer from Finomnis on Stack OverflowNewbie Question: String Slices
rust - String from slice - Stack Overflow
rust str slice from string - Stack Overflow
Confused by the purpose of str and String
I am coming from a world of Python, so pointers and references are kind of a new thing for me. So, I was going through The book. I was on the slices chapter, specifically the String Slices as Parameter part. I just don't get this fn first_word(s: &String) -> &str { is worse than fn first_word(s: &str) -> &str { this. Is it because it is a pointer to a pointer, if I understood things correctly?
Your code example is not very complete. The part that actually causes the error can't be seen in your example.
I guess that your code looks something like this:
pub fn function1(s: String) -> i32 {
let index: &i32 = &1;
let substring = (&s[index..]).to_string();
let counter = function1(substring);
10
}
error[E0277]: the type `String` cannot be indexed by `RangeFrom<&i32>`
--> src/main.rs:3:23
|
3 | let substring = (&s[index..]).to_string();
| ^^^^^^^^^^ `String` cannot be indexed by `RangeFrom<&i32>`
|
= help: the trait `Index<RangeFrom<&i32>>` is not implemented for `String`
Problems
indexmust be ausize, but it is an&i32. This is the main error that you see.- You cannot slice a string directly, you need to convert from char-based indices to byte-based indices first. This can be done by iterating through
char_indices().
Here is a rough sketch of how this might look like:
pub fn function1(s: String) -> i32 {
println!("s: {}", s);
let index: &i32 = &1;
// Try to convert the index to a byte position
let substring = match s.char_indices().nth(*index as usize) {
// If a position with the given index was found in the string, create a substring
Some((pos, _)) => (&s[pos..]).to_string(),
// Else, create an empty string
None => "".to_string(),
};
// Break if the substring is empty, otherwise we would have an infinite recursion
if substring.is_empty() {
return 0;
}
let counter = function1(substring);
counter + 1
}
fn main() {
let input_str = "ππππ€ͺ".to_string();
let result = function1(input_str);
println!("Result: {}", result);
}
s: ππππ€ͺ
s: πππ€ͺ
s: ππ€ͺ
s: π€ͺ
Result: 3
Slicing vs copying
With every iteration of your function, you are creating a new copy of the string. This is quite slow, and I don't see a reason why this would be necessary in your case.
What you really want is a slice of the input string. This doesn't copy any data, it simply references a part of the original string.
To achieve that, you would have to change your parameter type from String to &str. There is no reason your function would need to take ownership. Even if you want to take ownership, then to_string() would do so, as it creates a copy of the data. So there really is no reason to use String as the parameter type.
pub fn function1(s: &str) -> i32 {
println!("s: {}", s);
let index: &i32 = &1;
// Try to convert the index to a byte position
let substring = match s.char_indices().nth(*index as usize) {
// If a position with the given index was found in the string, create a substring slice
Some((pos, _)) => &s[pos..],
// Else, use an empty string
None => "",
};
// Break if the substring is empty, otherwise we would have an infinite recursion
if substring.is_empty() {
return 0;
}
let counter = function1(substring);
counter + 1
}
fn main() {
let input_str = "ππππ€ͺ".to_string();
let result = function1(&input_str);
println!("Result: {}", result);
}
s: ππππ€ͺ
s: πππ€ͺ
s: ππ€ͺ
s: π€ͺ
Result: 3
You couldn't indexing a string in rust, because strings are encoded in UTF-8.
You could use the method chars and/or char_indices
As from your given code, I can't figure out what method you should use. Have a look at the rust doc.
For further information:
https://doc.rust-lang.org/std/string/struct.String.html
https://doc.rust-lang.org/std/string/struct.String.html#method.chars
https://doc.rust-lang.org/std/string/struct.String.html#method.char_indices
https://doc.rust-lang.org/std/string/struct.String.html#method.split_whitespace