use core::{marker::Destruct, ops::{Residual, Try}};
use crate::{Bulk, IntoBulk, StaticBulk, option::MaybeLength};
#[rustc_on_unimplemented(
on(
any(Self = "&[{A}]", Self = "&[_]"),
message = "a slice of type `{Self}` cannot be collected since we need to store the elements somewhere",
label = "try explicitly collecting into a `Vec<{A}>`",
),
on(
all(any(A = "[{integer}]", A = "[{integer}; _]", A = "[{integer}; {integral}]", A = "Option<{integer}>"), any(Self = "&[{integral}]", Self = "&[{A}]", Self = "&[_]")),
message = "a slice of type `{Self}` cannot be collected since we need to store the elements somewhere",
label = "try explicitly collecting into a `Vec<{A}>`",
),
on(
any(Self = "[{A}]", Self = "[_]"),
message = "a slice of type `{Self}` cannot be collected since `{Self}` has no definite size",
label = "try explicitly collecting into a `Vec<{A}>`",
),
on(
all(any(A = "[{integer}]", A = "[{integer}; _]", A = "[{integer}; {integral}]", A = "Option<{integer}>"), any(Self = "[{integral}]", Self = "[{A}]", Self = "[_]")),
message = "a slice of type `{Self}` cannot be collected since `{Self}` has no definite size",
label = "try explicitly collecting into a `Vec<{A}>`",
),
on(
all(any(A = "[{A}]", A = "[_]"), any(Self = "[{A}; _]", Self = "[{A}; {integral}]", Self = "[_; _]", Self = "[_; {integral}]")),
message = "an array of type `{Self}` cannot be collected directly from a dynamically sized bulk",
label = "try collecting into a `Vec<{A}>`, then using `.try_into()`",
),
on(
all(A = "[{integer}]", any(Self = "[{integral}; _]", Self = "[{integral}; {integral}]", Self = "[{A}; _]", Self = "[{A}; {integral}]", Self = "[_; _]", Self = "[_; {integral}]")),
message = "an array of type `{Self}` cannot be collected directly from a dynamically sized bulk",
label = "try collecting into a `Vec<{A}>`, then using `.try_into()`",
),
on(
any(A = "[{A}]", A = "[_]"),
message = "a value of type `{Self}` cannot be collected from a dynamically sized bulk \
of elements of type `{A}`",
label = "value of type `{Self}` cannot be collected from dynamically sized bulk"
),
message = "a value of type `{Self}` cannot be collected from a bulk \
of structure `{A}`",
label = "value of type `{Self}` cannot be collected from bulk"
)]
pub const trait FromBulk<A>: Sized
where
A: CollectionAdapter + ?Sized
{
fn from_bulk<I>(bulk: I) -> Self
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item = <A as CollectionAdapter>::Elem>,
A: ~const CollectionStrategy<I::IntoBulk, Self>;
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item: ~const Try<Output = <A as CollectionAdapter>::Elem, Residual: ~const Residual<Self, TryType: ~const Try>> + ~const Destruct>,
A: ~const TryCollectionAdapter<I::IntoBulk, Self>;
}
pub trait CollectionAdapter
{
type Elem;
type Strategy<B, T>
where
B: Bulk;
type TryStrategy<B, T>
where
B: Bulk<Item: Try<Residual: Residual<T>>>;
#[cfg(feature = "alloc")]
type Nearest: FromBulk<Self>;
}
impl<A> CollectionAdapter for [A]
{
type Elem = A;
type Strategy<B, T> = B
where
B: Bulk;
type TryStrategy<B, T> = B
where
B: Bulk<Item: Try<Residual: Residual<T>>>;
#[cfg(feature = "alloc")]
type Nearest = alloc::vec::Vec<A>;
}
impl<A> CollectionAdapter for Option<A>
{
type Elem = A;
type Strategy<B, T> = B
where
B: Bulk;
type TryStrategy<B, T> = B
where
B: Bulk<Item: Try<Residual: Residual<T>>>;
#[cfg(feature = "alloc")]
type Nearest = Option<A>;
}
impl<A, const N: usize> CollectionAdapter for [A; N]
{
type Elem = A;
type Strategy<B, T> = T
where
B: Bulk;
type TryStrategy<B, T> = <<B::Item as Try>::Residual as Residual<T>>::TryType
where
B: Bulk<Item: Try<Residual: Residual<T>>>;
#[cfg(feature = "alloc")]
type Nearest = [A; N];
}
pub const trait CollectionStrategy<B, T>
where
B: ~const Bulk + ?Sized
{
fn adapt(bulk: B) -> Self::Strategy<B, T>
where
Self: CollectionAdapter<Elem = B::Item>,
B: Sized;
}
impl<A, B, T> CollectionStrategy<B, T> for [A]
where
B: Bulk + ?Sized
{
fn adapt(bulk: B) -> <Self as CollectionAdapter>::Strategy<B, T>
where
B: Sized
{
bulk
}
}
impl<A, B, const N: usize> const CollectionStrategy<B, [A; N]> for [A; N]
where
B: ~const Bulk<Item = A> + StaticBulk<Array<A> = [A; N]>
{
fn adapt(bulk: B) -> <Self as CollectionAdapter>::Strategy<B, [A; N]>
where
B: Sized
{
bulk.collect_array()
}
}
impl<A, B, const N: usize> const CollectionStrategy<B, Option<[A; N]>> for [Option<A>; N]
where
B: ~const Bulk<Item = Option<A>> + StaticBulk<Array<A> = [A; N]>,
A: ~const Destruct
{
fn adapt(bulk: B) -> <Self as CollectionAdapter>::Strategy<B, Option<[A; N]>>
where
B: Sized
{
bulk.try_collect_array()
}
}
impl<A, B, E, const N: usize> const CollectionStrategy<B, Result<[A; N], E>> for [Result<A, E>; N]
where
B: ~const Bulk<Item = Result<A, E>> + StaticBulk<Array<A> = [A; N]>,
A: ~const Destruct,
E: ~const Destruct
{
fn adapt(bulk: B) -> <Self as CollectionAdapter>::Strategy<B, Result<[A; N], E>>
where
B: Sized
{
bulk.try_collect_array()
}
}
impl<A, B> const CollectionStrategy<B, Option<A>> for Option<A>
where
B: ~const Bulk<Item = A, MinLength: MaybeLength, MaxLength: MaybeLength, Length: MaybeLength> + ?Sized
{
fn adapt(bulk: B) -> <Self as CollectionAdapter>::Strategy<B, Option<A>>
where
B: Sized
{
bulk
}
}
pub const trait TryCollectionAdapter<B, T>
where
B: ~const Bulk<Item: ~const Try<Residual: ~const Residual<T>>>
{
fn try_adapt(bulk: B) -> Self::TryStrategy<B, T>
where
Self: CollectionAdapter<Elem = <B::Item as Try>::Output>;
}
impl<A, B, T> TryCollectionAdapter<B, T> for [A]
where
B: Bulk<Item: Try<Residual: Residual<T>>>
{
fn try_adapt(bulk: B) -> <Self as CollectionAdapter>::TryStrategy<B, T>
{
bulk
}
}
impl<A, B, R, T, Y, const N: usize> const TryCollectionAdapter<B, [T; N]> for [A; N]
where
B: ~const Bulk<Item = R> + StaticBulk<Array<T> = [T; N]>,
R: ~const Try<Output = T, Residual: Residual<(), TryType: ~const Try> + ~const Residual<[T; N], TryType = Y> + ~const Destruct> + ~const Destruct,
Y: ~const Try<Residual: ~const Destruct>,
T: ~const Destruct
{
fn try_adapt(bulk: B) -> <Self as CollectionAdapter>::TryStrategy<B, [T; N]>
{
bulk.try_collect_array()
}
}
impl<A, T> FromBulk<[A]> for T
where
T: FromIterator<A>
{
fn from_bulk<I>(bulk: I) -> Self
where
I: IntoBulk<Item = A>
{
bulk.into_iter().collect()
}
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: IntoBulk<Item: Try<Output = A, Residual: Residual<Self>>>
{
bulk.into_iter().try_collect()
}
}
impl<A> const FromBulk<Option<A>> for Option<A>
where
A: ~const Destruct
{
fn from_bulk<I>(bulk: I) -> Self
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item = A>,
Option<A>: ~const CollectionStrategy<I::IntoBulk, Self>
{
bulk.into_bulk().first()
}
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item: ~const Try<Output = A, Residual: ~const Residual<Self, TryType: ~const Try>> + ~const Destruct>,
Option<A>: ~const TryCollectionAdapter<I::IntoBulk, Self>
{
Try::from_output(match bulk.into_bulk().first()
{
Some(result) => Some(result?),
None => None
})
}
}
impl<A, const N: usize> const FromBulk<[A; N]> for [A; N]
where
A: ~const Destruct
{
fn from_bulk<I>(bulk: I) -> Self
where
I: ~const IntoBulk<IntoBulk: ~const Bulk<Item = A>>,
[A; N]: ~const CollectionStrategy<I::IntoBulk, Self>
{
<[A; N] as CollectionStrategy<I::IntoBulk, Self>>::adapt(bulk.into_bulk())
}
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item: ~const Try<Output = A, Residual: ~const Residual<Self, TryType: ~const Try>>>,
[A; N]: ~const TryCollectionAdapter<I::IntoBulk, Self>
{
<[A; N] as TryCollectionAdapter<I::IntoBulk, Self>>::try_adapt(bulk.into_bulk())
}
}
impl<A, const N: usize> const FromBulk<[Option<A>; N]> for Option<[A; N]>
where
A: ~const Destruct
{
fn from_bulk<I>(bulk: I) -> Self
where
I: ~const IntoBulk<IntoBulk: ~const Bulk<Item = Option<A>>>,
[Option<A>; N]: ~const CollectionStrategy<I::IntoBulk, Self>
{
<[Option<A>; N] as CollectionStrategy<I::IntoBulk, Self>>::adapt(bulk.into_bulk())
}
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item: ~const Try<Output = Option<A>, Residual: ~const Residual<Self, TryType: ~const Try>>>,
[Option<A>; N]: ~const TryCollectionAdapter<I::IntoBulk, Self>
{
<[Option<A>; N] as TryCollectionAdapter<I::IntoBulk, Self>>::try_adapt(bulk.into_bulk())
}
}
impl<A, E, const N: usize> const FromBulk<[Result<A, E>; N]> for Result<[A; N], E>
where
A: ~const Destruct,
E: ~const Destruct
{
fn from_bulk<I>(bulk: I) -> Self
where
I: ~const IntoBulk<IntoBulk: ~const Bulk<Item = Result<A, E>>>,
[Result<A, E>; N]: ~const CollectionStrategy<I::IntoBulk, Self>
{
<[Result<A, E>; N] as CollectionStrategy<I::IntoBulk, Self>>::adapt(bulk.into_bulk())
}
fn try_from_bulk<I>(bulk: I) -> <<I::Item as Try>::Residual as Residual<Self>>::TryType
where
I: ~const IntoBulk<IntoBulk: ~const Bulk, Item: ~const Try<Output = Result<A, E>, Residual: ~const Residual<Self>>>,
[Result<A, E>; N]: ~const TryCollectionAdapter<I::IntoBulk, Self>
{
<[Result<A, E>; N] as TryCollectionAdapter<I::IntoBulk, Self>>::try_adapt(bulk.into_bulk())
}
}