accepts-codegen 0.0.1

Rust toolkit for composing synchronous and asynchronous acceptor pipelines
Documentation
use std::hash::BuildHasher;
use syn::{Ident, PredicateLifetime, PredicateType, Type, WherePredicate, punctuated::Punctuated};

use crate::common::collection::MergeMap;

use super::{merge_generic_params, merge_lifetimes, merge_type_param_bounds};

pub fn merge_where_predicates<P, S>(
    where_predicates: Punctuated<WherePredicate, P>,
    other_where_predicates: impl IntoIterator<Item = Punctuated<WherePredicate, P>>,
) -> Punctuated<WherePredicate, P>
where
    P: Default,
    S: BuildHasher + Default,
{
    let mut lifetime_map = MergeMap::<Ident, PredicateLifetime, _>::with_default(
        |existing: &mut PredicateLifetime, value| {
            existing.bounds =
                merge_lifetimes::<_, S>(std::mem::take(&mut existing.bounds), [value.bounds])
        },
    );

    let mut type_map = MergeMap::<Type, PredicateType, _>::with_default(|existing, value| {
        if let Some(mut bound_lifetimes) = existing.lifetimes.take() {
            bound_lifetimes.lifetimes = if let Some(s) = value.lifetimes {
                merge_generic_params::<_, S>(bound_lifetimes.lifetimes, [s.lifetimes])
            } else {
                merge_generic_params::<_, S>(bound_lifetimes.lifetimes, [])
            };
            existing.lifetimes = Some(bound_lifetimes);
        } else {
            existing.lifetimes = value.lifetimes;
        }

        existing.bounds =
            merge_type_param_bounds::<_, S>(std::mem::take(&mut existing.bounds), [value.bounds])
    });

    for where_predicate in where_predicates {
        match where_predicate {
            WherePredicate::Lifetime(lifetime_param) => {
                lifetime_map.upsert(lifetime_param.lifetime.ident.clone(), lifetime_param);
            }
            WherePredicate::Type(type_param) => {
                type_map.upsert(type_param.bounded_ty.clone(), type_param);
            }
            _ => {}
        }
    }

    for where_predicates in other_where_predicates {
        for where_predicate in where_predicates {
            match where_predicate {
                WherePredicate::Lifetime(lifetime_param) => {
                    lifetime_map.upsert(lifetime_param.lifetime.ident.clone(), lifetime_param);
                }
                WherePredicate::Type(type_param) => {
                    type_map.upsert(type_param.bounded_ty.clone(), type_param);
                }
                _ => {}
            }
        }
    }

    let mut new_where_predicates = Punctuated::new();

    for (_, lifetime_param) in lifetime_map.into_inner() {
        new_where_predicates.push(WherePredicate::Lifetime(lifetime_param));
    }
    for (_, type_param) in type_map.into_inner() {
        new_where_predicates.push(WherePredicate::Type(type_param));
    }

    new_where_predicates
}