Repository: diesel-rs/diesel
File: diesel/src/associations/belongs_to.rs (Rust)

Code before:
    /// # }
    /// ```
    fn try_grouped_by(
        self,
        parents: &'a [Parent],
    ) -> Result<Vec<Vec<Self::Item>>, TryGroupedByError<Self::Item>> {
        Ok(self.grouped_by(parents))
    }
}

/// A type of error which can be returned when attempting to group
/// a list of records.
///
/// If a child record has a nullable foreign key, or is being grouped
/// using a different relationship to the one that was used to query it,
/// it may not be possible to find a parent record it should be grouped by.
///
/// When encountering these missing relationships,
/// it may still be possible to group remaining records,
/// but would affect the contents of the returned values.
/// By extracting the contents of this struct, it is still possible
/// to use these resulting groups, as well as any records
/// that could not be grouped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct TryGroupedByError<Child> {
    /// The collection of records which were successfully indexed
    /// against a parent record.
    pub grouped: Vec<Vec<Child>>,
    /// The collection of records that could not be indexed
    /// against a parent record.
    pub ungrouped: Vec<Child>,
}

type Id<T> = <T as Identifiable>::Id;

impl<'a, Parent: 'a, Child, Iter> GroupedBy<'a, Parent> for Iter
where
    Iter: IntoIterator<Item = Child>,
    Child: BelongsTo<Parent>,
    &'a Parent: Identifiable,
    Id<&'a Parent>: Borrow<Child::ForeignKey>,
{
    fn grouped_by(self, parents: &'a [Parent]) -> Vec<Vec<Child>> {
        use std::collections::HashMap;

        let id_indices: HashMap<_, _> = parents
            .iter()
            .enumerate()
            .map(|(i, u)| (u.id(), i))
            .collect();
        let mut result = parents.iter().map(|_| Vec::new()).collect::<Vec<_>>();

Review comment (suggestion):
```suggestion
#[non_exhaustive]
pub struct TryGroupedByError<Child> {
```

we don't want to allow people to deconstruct this completely.

Maybe we want also to add a constructor to allow adding fields in a backward compatible way later on

Code after:
    /// # }
    /// ```
    fn try_grouped_by(
        self,
        parents: &'a [Parent],
    ) -> Result<Vec<Vec<Self::Item>>, TryGroupedByError<Self::Item>> {
        Ok(self.grouped_by(parents))
    }
}

/// A type of error which can be returned when attempting to group
/// a list of records.
///
/// If a child record has a nullable foreign key, or is being grouped
/// using a different relationship to the one that was used to query it,
/// it may not be possible to find a parent record it should be grouped by.
///
/// When encountering these missing relationships,
/// it may still be possible to group remaining records,
/// but would affect the contents of the returned values.
/// By extracting the contents of this struct, it is still possible
/// to use these resulting groups, as well as any records
/// that could not be grouped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[non_exhaustive]
pub struct TryGroupedByError<Child> {
    /// The collection of records which were successfully indexed
    /// against a parent record.
    pub grouped: Vec<Vec<Child>>,
    /// The collection of records that could not be indexed
    /// against a parent record.
    pub ungrouped: Vec<Child>,
}

type Id<T> = <T as Identifiable>::Id;

impl<Child> TryGroupedByError<Child> {
    /// Creates a `TryGroupedByError`.
    ///
    /// This is generally used by methods like [`GroupedBy::try_grouped_by`].
    pub fn new(grouped: Vec<Vec<Child>>, ungrouped: Vec<Child>) -> Self {
        Self { grouped, ungrouped }
    }
}

impl<'a, Parent: 'a, Child, Iter> GroupedBy<'a, Parent> for Iter
where
    Iter: IntoIterator<Item = Child>,
    Child: BelongsTo<Parent>,
    &'a Parent: Identifiable,
    Id<&'a Parent>: Borrow<Child::ForeignKey>,