use std::borrow::{Cow, ToOwned};
mod carrier;
mod expression;
mod schema;
pub use carrier::Carrier;
pub(crate) use carrier::{carrier_into_inner_opt, carrier_try_none};
pub use self::expression::{ExpressionDepthChecker, ExpressionTransform};
pub use self::schema::{SchemaDepthChecker, SchemaTransform};
#[macro_export]
macro_rules! transform_output_type {
(|$lt:lifetime, $T:ident| $out:ty) => {
type Output<$T: ::std::borrow::ToOwned + ?Sized + $lt> = $out;
type Residual = <Self::Output<()> as $crate::transforms::Carrier<$lt, ()>>::Residual;
};
}
#[doc(inline)]
pub use transform_output_type;
pub(crate) fn map_owned_children_or_else<'a, Parent, Child, ChildCarrier, ParentCarrier, R>(
parent: &'a Parent,
children: impl ExactSizeIterator<Item = ChildCarrier>,
map_owned: impl FnOnce(Vec<<Child as ToOwned>::Owned>) -> <Parent as ToOwned>::Owned,
) -> ParentCarrier
where
Parent: ToOwned + ?Sized,
Child: ToOwned + ?Sized + 'a,
ChildCarrier: Carrier<'a, Child, Residual = R>,
ParentCarrier: Carrier<'a, Parent, Residual = R>,
{
let num_children = children.len();
let mut num_borrowed = 0;
let mut new_children = Vec::with_capacity(num_children);
for child in children {
if let Some(transformed) = carrier_into_inner_opt!(child) {
if let Cow::Borrowed(_) = transformed {
num_borrowed += 1;
}
new_children.push(transformed);
}
}
if new_children.is_empty() {
carrier_try_none!();
}
if num_borrowed < num_children {
let owned = new_children.into_iter().map(Cow::into_owned).collect();
Carrier::from_inner(Cow::Owned(map_owned(owned)))
} else {
Carrier::from_inner(Cow::Borrowed(parent))
}
}
pub(crate) fn map_owned_pair_or_else<'a, Parent, Child, ChildCarrier, ParentCarrier, R>(
parent: &'a Parent,
left: ChildCarrier,
right: ChildCarrier,
map_owned: impl FnOnce((Child::Owned, Child::Owned)) -> Parent,
) -> ParentCarrier
where
Parent: Clone,
Child: ToOwned + ?Sized + 'a,
ChildCarrier: Carrier<'a, Child, Residual = R>,
ParentCarrier: Carrier<'a, Parent, Residual = R>,
{
let left = carrier_into_inner_opt!(left);
let right = carrier_into_inner_opt!(right);
let (Some(left), Some(right)) = (left, right) else {
carrier_try_none!();
unreachable!();
};
Carrier::from_inner(match (left, right) {
(Cow::Borrowed(_), Cow::Borrowed(_)) => Cow::Borrowed(parent),
(left, right) => Cow::Owned(map_owned((left.into_owned(), right.into_owned()))),
})
}
pub(crate) fn map_owned_or_else<'a, Parent, Child, ChildCarrier, ParentCarrier, R>(
parent: &'a Parent,
child: ChildCarrier,
map_owned: impl FnOnce(Child::Owned) -> Parent,
) -> ParentCarrier
where
Parent: Clone,
Child: ToOwned + ?Sized + 'a,
ChildCarrier: Carrier<'a, Child, Residual = R>,
ParentCarrier: Carrier<'a, Parent, Residual = R>,
{
let child = carrier_into_inner_opt!(child);
let Some(child) = child else {
carrier_try_none!();
unreachable!();
};
Carrier::from_inner(match child {
Cow::Owned(v) => Cow::Owned(map_owned(v)),
Cow::Borrowed(_) => Cow::Borrowed(parent),
})
}