Conversion of Iterator Elements inside Arc

Let's say I have the following struct and a wrapper:

#[derive(Clone)]
struct Person;

#[derive(Clone)]
struct WrappedPerson(Person);

My initial assumption is that this is an idiomatic way to convert between the two:

impl From<WrappedPerson> for Person {
    fn from(wrapper: WrappedPerson) -> Self {
        wrapper.0
    }
}

Furthermore, I have a Vec<Arc<WrappedPerson>> that I map into a Vec<Person> and instead of doing this...

fn into_unwrapped_vec(wrapped_persons: Vec<Arc<WrappedPerson>>) -> Vec<Person>{
    wrapped_persons
        .into_iter()
        .map(|person| person.0.clone())
        .collect()
}

... I would like to manipulate the values like so:

// Does not compile:
fn into_unwrapped_vec(wrapped_persons: Vec<Arc<WrappedPerson>>) -> Vec<Person>{
    wrapped_persons
        .into_iter()
        .map(Into::into)
        .collect()
}

Because

  1. Using the From/Into traits and function references look like the more idiomatic approach to me,
  2. the inner field may change, or even worse, access to it may not always be guaranteed. Another point for Into.

I understand the compiler error. The trait is not implemented for Arc<WrappedPerson>. However, I am blanking on how to de-reference the iterator elements in a way that I am allowed to call WrappedPerson::into. How would I accomplish this?

Arc::unwrap_or_clone is probably what you want, and while that's still unstable, the implementation is easy enough to write yourself:

Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone())
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.