Home > Blockchain >  Allow Vec of custom type to be joined with &str
Allow Vec of custom type to be joined with &str

Time:10-03

I want a Vec<CustomType> to be joinable by &str. Here is a minimal example of what I've tried so far:

#[derive(Debug)]
struct Item {
    string: String,
}

impl Item {
    pub fn new(string: impl Into<String>) -> Self {
        Self {
            string: string.into(),
        }
    }

    pub fn to_string(&self) -> &String {
        &self.string
    }
}

impl From<&Item> for &String {
    fn from(item: &Item) -> Self {
        &item.string
    }
}

impl From<&Item> for &str {
    fn from(item: &Item) -> Self {
        &item.string.to_string()
    }
}

fn main() {
    let items = Vec::from([Item::new("Hello"), Item::new("world")]);
    let string = items.join(" ");
    println!("{}", string);
}

Which results in the error:

 $ rustc jointrait.rs 
error[E0599]: the method `join` exists for struct `Vec<Item>`, but its trait bounds were not satisfied
  --> jointrait.rs:32:24
   |
32 |     let string = items.join(" ");
   |                        ^^^^ method cannot be called on `Vec<Item>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `[Item]: Join<_>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.

The rustc help just says that some method is missing, but googling the error, I could not find out which method / trait I need to implement.

CodePudding user response:

In order for a list of Ts to be joinable, [T] needs to implement Join<Separator>.

If you look which things already implement Join, you will find the following entry:

impl<S> Join<&str> for [S]
where
    S: Borrow<str>

This means, everything that implements Borrow<str> can be joined by a &str separator. So all you have to do is implement Borrow<str> for your struct:

use std::borrow::Borrow;

#[derive(Debug)]
struct Item {
    string: String,
}

impl Item {
    pub fn new(string: impl Into<String>) -> Self {
        Self {
            string: string.into(),
        }
    }
}

impl Borrow<str> for Item {
    fn borrow(&self) -> &str {
        &self.string
    }
}

fn main() {
    let items = Vec::from([Item::new("Hello"), Item::new("world")]);
    let string = items.join(" ");
    println!("{}", string);
}
Hello world
  • Related