0

I have two identical structs in two different modules:

Module data has struct data::Branch:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Branch {
    pub id: Uuid,
    pub name: String,
    pub parents: Vec<Branch>,
    pub children: Vec<Branch>,
}

And module graphql has struct graphql::Branch:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Branch {
    pub id: Uuid,
    pub name: String,
    pub parents: Vec<Branch>,
    pub children: Vec<Branch>,
}

I can not figure it out how to implement impl From<Vec<data::Branch>> for Vec<Branch> in graphql module?

impl From<data::branch::Branch> for Branch {
    fn from(branch: data::branch::Branch) -> Branch {
        Branch {
            id: branch.id,
            name: branch.name,
            content: branch.name,
            parents: branch.parents.into(),
            children: branch.children.into(),
            created_at: branch.created_at,
            updated_at: branch.updated_at,
        }
    }
}

impl From<Vec<data::branch::Branch>> for Vec<Branch> {
    fn from(_: Vec<data::branch::Branch>) -> Self {
        todo!();
    }
}

I have faced this error and don't know how to handle it.

error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
  --> src/graphql/branch/branch.rs:64:1
   |
64 | impl From<Vec<data::branch::Branch>> for Vec<Branch> {
   | ^^^^^-------------------------------^^^^^-----------
   | |    |                                   |
   | |    |                                   `Vec` is not defined in the current crate
   | |    `Vec` is not defined in the current crate
   | impl doesn't use only types from inside the current crate
   |
   = note: define and implement a trait or new type instead
  • 3
    The short answer is you can't due to the orphan rules. I recommend you just use the same type in both cases. If neither is a better owner maybe create a `types` module for it? – cafce25 Dec 30 '22 at 19:24
  • 2
    Just make the conversion a free function instead of using the `From` trait. – kmdreko Dec 30 '22 at 19:37
  • 1
    Related if not a duplicate: [Does Rust implement From> for Vec if I have already implemented From for U?](/q/65328977/2189130) or even [In Rust, how to define a generic function for converting Vec to Vec](/q/70014181/2189130) – kmdreko Dec 30 '22 at 19:48

1 Answers1

0

As I understand now simple generic function can easily handle such case. Thank you @kmdreko for your help.

It works for me. The only problem is that the compiler suggests implementing From<Vec<data::Branch>> for Vec<Branch>, but you can't do it, and this is a little bit confusing if you don't know rust well)

rust playground.

mod data {
    #[derive(Debug, Clone, Default)]
    pub struct Branch {
        pub id: String,
        pub name: String,
        pub parents: Vec<Branch>,
        pub children: Vec<Branch>,
    }
}

#[derive(Debug, Clone)]
pub struct Branch {
    pub id: String,
    pub name: String,
    pub parents: Vec<Branch>,
    pub children: Vec<Branch>,
}

impl From<data::Branch> for Branch {
    fn from(branch: data::Branch) -> Branch {
        Branch {
            id: branch.id.clone(),
            name: branch.name.clone(),
            parents: convert_from_vec(branch.parents.clone()),
            children: convert_from_vec(branch.children.clone()),
        }
    }
}

fn convert_from_vec<T, U>(v: Vec<U>) -> Vec<T>
where
    T: From<U>,
{
    v.into_iter().map(T::from).collect()
}

fn main() {
    let branch = data::Branch::default();
    let branch: Branch = branch.into();
}