Learning Rust: Rust way to program palindrome

I have C background, so coded the task in C completely different. However I decided to rewrite my C solutions in Rust. So question is - is the code appropriate for Rust?

trait CharLen {
    fn char_len(&self) -> usize;
}

impl CharLen for str {
    fn char_len(&self) -> usize {
        self.chars().count()
    }
}
/// makes a string to palindrome
pub fn palindrome(s: &str) -> String {
    let char_len = s.char_len();
    let len = s.len();
    let odd = char_len % 2 != 0;
    let mut rev_s = s.chars().rev();
    let center_len = if !odd {
        0
    } else {
        rev_s.next().unwrap().len_utf8()
    };
    let mut res = String::with_capacity(if odd { len * 2 - center_len } else { len << 1 });
    for c in s.chars() {
        res.push(c)
    }
    for c in rev_s {
        res.push(c)
    }
    res
}

As a Rust programmer, how would you implemented the code more efficient and in Rust way?

This is the test block:

mod palindrome;
use palindrome::palindrome;
fn main() -> Result<(), Box<dyn std::error::Error>> {

    println!("{}", palindrome("¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·"));
    println!("{}", palindrome("Ղ"));
    println!("{}", palindrome(""));
    Ok(())
}
pub fn palindrome(s: &str) -> String {
    s.chars()
        .chain(s.chars().rev().skip(s.chars().count() % 2))
        .collect()
}
1 Like

I doubt the 1-4 bytes in allocation difference is worth saving, so even when anticipating micro optimizations:

    let mut rev = s.chars().rev();
    if 1 == s.chars().count() % 2 {
        let _ = rev.next();
    }
    let mut res = String::with_capacity(s.len() * 2);
    res.push_str(s);
    res.extend(rev);
    res

But you could do something like

    let mut res = match s.chars().count() % 2 {
        0 => String::with_capacity(s.len() * 2),
        _ => String::with_capacity(s.len() * 2 - rev.next().unwrap().len_utf8()),
    };

if you preferred.

(And I'd document the behavior, since it's not self-evident.)

You probably want to operate on graphemes, not chars.

It's a very good suggestion making the code looking "rusty".

It is an interesting view. Since palindrome was first used in the 6th century BC by the Athenian philosopher Epicharmus in his play "The Gods of the Underworld", I doubt that Epicharmus thought so far. But as you pointed, I can step back and using an iterator created by one of the mentioned crates.