Implement the reverse trait for strings

trait str self impl

I wanted to see how to add a new trait to strings. I thought reversing would be a simple way to demonstrate this. Apparently, the implementation of the string revere I used will fail on certain Unicode strings. So there is a crate called unicode_reverse for the real solution, if you need that.

This article primarily is for demonstrating how to add the trait.

We would like to have a function that can reverse a string and then we would like to turn it into a method. First we would like to have

println!("{}", reverse_string(text));

and then

println!("{}", text.reverse());

Create a crate

cargo new reverse-trait-for-strings
cd reverse-trait-for-strings

print Hello World!

Edit the src/main.rs file:

fn main() {
    let text = "Hello, world!";
    println!("{}", text);
}

This works.

Try to call the reverse method

fn main() {
    let text = "Hello, world!";
    println!("{}", text);
    println!("{}", text.reverse());
}

This will give an error:

no method named reverse found for reference &str in the current scope

Implement the reverse_string function

fn main() {
    let text = "Hello, world!";
    println!("{}", text);

    println!("{}", reverse_string(text));
}

fn reverse_string(text: &str) -> String {
    text.chars().rev().collect::<String>()
}
cargo run

Hello, world!
!dlrow ,olleH

Create the Reverse trait with a function

This is the base implementation of the reverse method. It defines the signature of this method.

trait Reverse {
    fn reverse(&self) -> String;
}

Implement the reverse method for str

Inside we could have called the reverse_string function in order to avoid code duplication, but my point here is that we don't need that function for the trait.

impl Reverse for str {
    fn reverse(&self) -> String {
        self.chars().rev().collect::<String>()
    }
}

Now we can already use the reverse method:

fn main() {
    let text = "Hello, world!";
    println!("{}", text);
    println!("{}", text.reverse());
}

The full source code

examples/reverse-trait-for-strings/src/main.rs

fn main() {
    let text = "Hello, world!";
    println!("{}", text);
    // println!("{}", text.reverse());
    // no method named `reverse` found for reference `&str` in the current scope

    println!("{}", reverse_string(text));
    println!("{}", text.reverse());
}

fn reverse_string(text: &str) -> String {
    text.chars().rev().collect::<String>()
}

trait Reverse {
    fn reverse(&self) -> String;
}

impl Reverse for str {
    fn reverse(&self) -> String {
        self.chars().rev().collect::<String>()
    }
}

Making the trait reusable

It is nice to create a trait for the crate we are working on, but it would be even better if we could make it reusable so other people on our team, in our company, or around the world could use it. The solution is to create a crate providing the trait.

Related Pages

Implement the reverse trait for strings in a reusable crate
Implement the reverse trait for strings in a reusable crate

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo