Modifying a String (or &str) by indexing

⚓ Rust    📅 2025-09-12    👤 surdeus    👁️ 9      

surdeus

Warning

This post was published 62 days ago. The information described in this article may have changed.

As part of learning Rust, I chose to convert a word scrambling code from a C++ example. The C++ is pretty straightforward and in fact could just as well be C with a null-terminated string and using strlen (although in modern C++ the last three statements would probably be done with std::swap():

string jumble = word;
int len = jumble.size();
for (int i = 0; i < len; ++i) {
    int idx1 = (rand() % len);
    int idx2 = (rand() % len);
    char tmp = jumble[idx1];
    jumble[idx1] = jumble[idx2];
    jumble[idx2] = tmp;
}

At first I banged my head against the compiler because word and jumble where &str and it kept telling me I couldn't index into it, or something didn't have a size or, of course, I couldn't borrow immutably twice. My implementation stands as follows:

let mut jumble = String::from(word);
let len = jumble.len();
for _ in 0..len {
    let idx1 = rng.random_range(0..len) as usize;
    let idx2 = rng.random_range(0..len) as usize;
    let tmp = &jumble.clone()[idx1..idx1 + 1];
    jumble.replace_range(idx1..idx1 + 1, &jumble.clone()[idx2..idx2 + 1]);
    jumble.replace_range(idx2..idx2 + 1, tmp);
}

I understand that indexing into UTF-8 strings is not advisable, even if one knows the strings are all plain ASCII. However, the "solution" appears to be doing a lot of unnecessary work compared to the C/C++ version (I haven't looked at the generated code). OTOH, a fully UTF-8 compliant solution would probably have to convert jumble to Rust chars to swap same-sized items with ease (I hope) and then revert the result to a String.
Anyway, if there's a more idiomatic way to do the above (other than the Unicode conversion), please let me know.

5 posts - 4 participants

Read full topic

🏷️ Rust_feed