How to split string into chunks in Rust to insert spaces

If the size of the data you want to split in is fixed then:

use std::str;

fn main() {
    let subs = "‌​‌​‌​​‌​‌".as_bytes()
        .chunks(7)
        .map(str::from_utf8)
        .collect::<Result<Vec<&str>, _>>()
        .unwrap();
        
    println!("{:?}", subs);
}

// >> ["&#8204;", "&#8203;", "&#8204;", "&#8203;", "&#8204;", "&#8203;", "&#8203;", "&#8204;", "&#8203;", "&#8204;"]

So if you want to work from a list of chars to create a String, you can use fold for that.

Something like this :

text.chars
    .enumerate()
    .fold(String::new(), |acc, (i, c)| {
        if i != 0 && i == n {
            format!("{} {}", acc, c)
        } else {
            format!("{}{}", acc, c)
        }
    })

Such a simple task can be solved with a single loop:

fn main() {
    let n = 4;
    let text = "whatupmyname";
    let mut result = String::new();

    for (i, c) in text.chars().enumerate() {
        result.push(c);
        if (i + 1) % n == 0 {
            result.push(' ');
        }
    }
    println!("{:?}", result); // "what upmy name "
}

The problem here is that chars() and bytes() return Iterators, not slices. You could use as_bytes(), which will give you a &[u8]. However, you cannot directly get a &[char] from a &str, because there only exists the bytes themselves, and the chars must be created by looking through and seeing how many bytes makes up each one. You'd have to do something like this:

text.chars()
    .collect::<Vec<char>>()
    .chunks(n)
    .map(|c| c.iter().collect::<String>())
    .collect::<Vec<String>>()
    .join(" ");

However, I would NOT recommend this as it has to allocate a lot of temporary storage for Vecs and Strings along the way. Instead, you could do something like this, which only has to allocate to create the final String.

text.chars()
    .enumerate()
    .flat_map(|(i, c)| {
        if i != 0 && i % n == 0 {
            Some(' ')
        } else {
            None
        }
        .into_iter()
        .chain(std::iter::once(c))
    })
    .collect::<String>()

This stays as iterators until the last collect, by flat_mapping with an iterator that is either just the character or a space and then the character.