Help to make code more consise when using Cow

⚓ Rust    📅 2025-10-10    👤 surdeus    👁️ 4      

surdeus

I have the following code:

use std::borrow::Cow;

pub fn json_encode(orig: &str) -> Cow<'_, str> {
    let mut chars = orig.char_indices();
    let mut owned = false;
    let mut res = String::new();
    while let Some( (i,c) ) = chars.next() {
        match c {
            '"' => { res = orig[..i].to_string();
                res.push_str("\\\""); owned = true;
                break},
            '\n' => { res = orig[..i].to_string();
                res.push_str("\x5Cn"); owned = true;
                break},
            '\r' => { res = orig[..i].to_string();
                res.push_str("\x5cr"); owned = true;
                break},
            '\t' => { res = orig[..i].to_string(); 
                res.push_str("\x5ct"); owned = true;
                break},
            '\\' => { res = orig[..i].to_string();
                res.push_str("\x5c\x5c"); owned = true;
                break},
            _ => () ,
        }
    }
    if owned {
        while let Some( (_,c) ) = chars.next() {
            match c {
                '"' => res.push_str("\\\""),
                '\n' => res.push_str("\x5Cn"),
                '\r' => res.push_str("\x5cr"),
                '\t' => res.push_str("\x5ct"),
                '\\' => res.push_str("\x5c\x5c"),
                _ => res.push(c),
            }
        }
        Cow::Owned(res)
    } else {
        Cow::Borrowed(orig)
    }
}


fn main() {
    let value = json_encode(r#"Hello " \ "
        world!"#);
    println!("{}", value);
    let value = json_encode("Hello world!");
    println!("{}", value);
}

It's working, however, I do not like that res string is created regardless if returned the borrowed or an owned value. I tried to declare it without an initialization, but I couldn't convince the compiler - it's okay in the borrowed case.

res = orig[..i].to_string(); looks like a boilerplate, and I couldn't figure out how to get rid of it.

Finally, since I know approximately a length of owned value, I would prefer to set it explicitly.

Any other improvements you could see?

4 posts - 3 participants

Read full topic

🏷️ Rust_feed