/*!
Contains traits for accessing multiple fields at once.
*/
use crate::;
use SelfOps;
/// Queries the type returned by the
/// `RevGetMultiFieldImpl::rev_get_multi_field_impl` method.
/// This is some collection of references.
pub type RevGetMultiFieldImplOut<'a, Path, This> =
UnnormFields;
/// Queries the type returned by the
/// `RevGetMultiFieldMutImpl::rev_get_multi_field_mut_impl` method.
/// This is some collection of mutable references.
pub type RevGetMultiFieldMutImplOut<'a, Path, This> =
UnnormFieldsMut;
/// Queries the type returned by the
/// `RevGetMultiFieldMutImpl::rev_get_multi_field_raw_mut_impl` method.
/// This is some collection of mutable pointers.
pub type RevGetMultiFieldMutImplRaw<'a, Path, This> =
UnnormFieldsRawMut;
/// Queries the type returned by the
/// `RevIntoMultiFieldImpl::rev_into_multi_field_impl` method.
/// This is some collection of values.
pub type RevIntoMultiFieldImplOut<Path, This> =
UnnormIntoFields;
/// Queries the type returned by the
/// `RevGetMultiField::rev_get_multi_field` method.
/// This is some collection of references.
pub type RevGetMultiFieldOut<'a, Path, This> = Fields;
/// Queries the type returned by the
/// `RevGetMultiFieldMut::rev_get_multi_field_mut` method.
/// This is some collection of mutable references.
pub type RevGetMultiFieldMutOut<'a, Path, This> =
FieldsMut;
/// Queries the type returned by the
/// `RevGetMultiFieldMut::rev_get_multi_field_raw_mut` method.
/// This is some collection of mutable pointers.
pub type RevGetMultiFieldMutRaw<'a, Path, This> =
FieldsRawMut;
/// Queries the type returned by the
/// `RevIntoMultiField::rev_into_multi_field` method.
/// This is some collection of values.
pub type RevIntoMultiFieldOut<Path, This> = IntoFields;
/// Gets references to multiple fields from `This`,
/// usually a tuple of `Result<&_, E: IsFieldErr>`s,
///
/// `This` is the type we are accessing,and `Self` is a field path.
///
/// To get `Option<&_>` or `&_` instead of each of those `Result`s,
/// you can use the [`RevGetMultiField`] as a bound instead.
///
/// [`RevGetMultiField`]: ./trait.RevGetMultiField.html
///
/// # Usage as bound
///
/// This trait shouldn't be used as a bound,except in implementations of the same trait.
///
/// For a trait that can be used in bounds,you can use [`RevGetMultiField`] (it has examples).
///
/// # Example
///
/// This example demonstrates how you can implement `RevGetMultiFieldImpl` to get a
/// pair of indices.
///
/// ```rust
/// use structural::field::{FailedAccess, RevGetMultiFieldImpl};
/// use structural::path::{AliasedPaths, IsMultiFieldPath};
/// use structural::StructuralExt;
///
/// struct Pair(usize,usize);
///
/// impl IsMultiFieldPath for Pair{
/// type PathUniqueness= AliasedPaths;
/// }
///
/// impl<'a,T:'a> RevGetMultiFieldImpl<'a,[T]> for Pair{
/// type UnnormFields=(
/// Result<&'a T,FailedAccess>,
/// Result<&'a T,FailedAccess>,
/// );
///
/// fn rev_get_multi_field_impl(self, this: &'a [T]) -> Self::UnnormFields{
/// (
/// this.get(self.0).ok_or(FailedAccess),
/// this.get(self.1).ok_or(FailedAccess),
/// )
/// }
/// }
///
/// let arr=[2,3,5,8,13,21,34,55,89];
///
/// assert_eq!( arr[..].fields(Pair(2,1)), (Some(&5),Some(&3)) );
/// assert_eq!( arr[..].fields(Pair(0,3)), (Some(&2),Some(&8)) );
///
/// ```
///
/// Gets references to multiple fields from `This`,
/// usually a tuple of `Option<&_>`s and `&_`s
///
/// This trait has a blanket implementation for the [`RevGetMultiFieldImpl`] trait,
/// implementing that trait is necessary to be able to use this trait.
///
/// This is used by the
/// [`StructuralExt::fields`](../../trait.StructuralExt.html#method.fields),
/// and [`StructuralExt::cloned_fields`](../../trait.StructuralExt.html#method.cloned_fields)
/// methods.
///
/// There's also the [`RevGetMultiFieldOut`] type alias to get this trait's
/// [`Fields`] associated type.
///
/// # Example
///
/// This demonstrates how you can use `RevGetMultiField` with structs.
///
/// ```rust
/// use structural::{StructuralExt, FP, fp};
/// use structural::field::RevGetMultiField;
/// use structural::for_examples::{Tuple2, Tuple3};
///
/// use std::cmp::Ordering;
///
/// fn access_fields<'a,T,O0,O1>(this: &'a T)->(&'a O0,&'a O1)
/// where
/// // The `Fields= (&'a O0,&'a O1)` constraint ensures that the return type is a pair.
/// FP!(0,1): RevGetMultiField<'a,T,Fields= (&'a O0,&'a O1)>
/// {
/// this.fields(fp!(0,1))
/// }
///
/// let tup2 = Tuple2(Some(8), Ordering::Less);
/// let tup3 = Tuple3(Some("hello"), Some(true), 34);
///
/// assert_eq!( access_fields(&tup2), (&Some(8), &Ordering::Less) );
/// assert_eq!( access_fields(&tup3), (&Some("hello"), &Some(true)) );
///
/// ```
///
/// # Example
///
/// This demonstrates how you can use `RevGetMultiField` with enums.
///
/// ```rust
/// use structural::{StructuralExt, FP};
/// use structural::path::IntoAliasingOut;
/// use structural::field::{RevGetMultiField,RevGetMultiFieldOut};
/// use structural::for_examples::{Bomb, WithBoom};
///
/// use std::cmp::Ordering;
///
/// // Used `IntoAliasingOut` here to make the path safely constructible,
/// // since cosntructing a `NestedFieldPathSet<_,_,UniquePaths>`
/// // (what `FP!(::Boom=>a,b)` desugars into) requires unsafe code to construct,
/// // while `NestedFieldPathSet<_,_,AliasedPaths>`
/// // (what `IntoAliasingOut` turns `FP!(::Boom=>a,b)` into)
/// // does not require unsafe code to construct
/// //
/// // While this is safely constructible,it can't be used to do multiple mutable borrows,
/// // you can use `field_path_aliases` to avoid writing `unsafe` code in that case.
/// type ThePath=IntoAliasingOut<FP!(::Boom=>a,b)>;
///
/// fn access_fields<'a,T,O0,O1>(this: &'a T)->Option<(&'a O0,&'a O1)>
/// where
/// // The `Fields= Option<(&'a O0,&'a O1)>` constraint ensures that
/// // the return type is an optional pair.
/// ThePath: RevGetMultiField<'a,T,Fields= Option<(&'a O0,&'a O1)>>
/// {
/// this.fields(ThePath::NEW)
/// }
///
/// fn main(){
/// let with_0 = WithBoom::Nope;
/// let with_1 = WithBoom::Boom{a:"hi", b: &[0,1,2]};
/// assert_eq!( access_fields(&with_0), None );
/// assert_eq!( access_fields(&with_1), Some((&"hi", &&[0,1,2][..])) );
///
/// let bomb_0 = Bomb::Nope;
/// let bomb_1 = Bomb::Boom{a:"hello", b: &[5,8,13]};
/// assert_eq!( access_fields(&bomb_0), None );
/// assert_eq!( access_fields(&bomb_1), Some((&"hello", &&[5,8,13][..])) );
/// }
///
/// ```
///
/// [`RevGetMultiFieldImpl`]: ./trait.RevGetMultiFieldImpl.html
///
/// [`Fields`]: ./trait.RevGetMultiField.html#associatedtype.Fields
///
/// [`RevGetMultiFieldImpl::rev_get_multi_field`]:
/// ./trait.RevGetMultiFieldImpl.html#tymethod.rev_get_multi_field
//////////////////////////////////////////////////////////////////////////
/// Gets mutable references to multiple fields from `This`,
/// usually returning a tuple of `Result<&mut _, E: IsFieldErr>`s,
///
/// `This` is the type we are accessing,and `Self` is a field path.
///
/// To get `Option<&mut _>`s and `&mut _`s instead of each of those `Result`s,
/// you can use the [`RevGetMultiFieldMut`] as a bound instead.
///
/// # Safety
///
/// The [`rev_get_multi_field_raw_mut_impl`] method must return non-aliasing pointers,
/// where all of them are safe to dereference.
///
/// As a reminder: mutable references imply uniqueness,
/// which means that it's undefined behavior for implementors to
/// return multiple mutable references to the same field from [`rev_get_multi_field_mut_impl`].
///
/// [`RevGetMultiFieldMut`]: ./trait.RevGetMultiFieldMut.html
/// [`rev_get_multi_field_raw_mut_impl`]: #tymethod.rev_get_multi_field_raw_mut_impl
/// [`rev_get_multi_field_mut_impl`]: #tymethod.rev_get_multi_field_mut_impl
///
///
/// # Example
///
/// This example demonstrates how you can implement `RevGetMultiFieldMutImpl` to get a
/// pair of indices.
///
/// ```rust
/// use structural::field::{FailedAccess, RevGetMultiFieldMutImpl};
/// use structural::path::{IsMultiFieldPath, UniquePaths};
/// use structural::StructuralExt;
///
/// let mut arr=[2,3,5,8,13,21,34,55,89];
///
/// assert_eq!( arr[..].fields_mut(Pair::new(2,1)), (Some(&mut 5),Some(&mut 3)) );
/// assert_eq!( arr[..].fields_mut(Pair::new(0,3)), (Some(&mut 2),Some(&mut 8)) );
///
/// mod pair{
/// pub struct Pair(usize,usize);
/// impl Pair {
/// pub fn first(&self)->usize{
/// self.0
/// }
/// pub fn second(&self)->usize{
/// self.1
/// }
/// pub fn new(first:usize, second:usize)->Self{
/// assert_ne!(first,second,"Expected disjoint indices");
/// Pair(first, second)
/// }
/// }
/// }
/// use pair::Pair;
///
/// impl IsMultiFieldPath for Pair{
/// type PathUniqueness= UniquePaths;
/// }
///
/// unsafe impl<'a,T:'a> RevGetMultiFieldMutImpl<'a,[T]> for Pair{
/// type UnnormFieldsMut=(
/// Result<&'a mut T,FailedAccess>,
/// Result<&'a mut T,FailedAccess>,
/// );
///
/// type UnnormFieldsRawMut=(
/// Result<*mut T,FailedAccess>,
/// Result<*mut T,FailedAccess>,
/// );
///
/// fn rev_get_multi_field_mut_impl(self, this: &'a mut [T]) -> Self::UnnormFieldsMut{
/// // Pair ensures that the indices are disjoint in its constructor,
/// // so there can't be overlapping mutable references.
/// unsafe{
/// let ret=self.rev_get_multi_field_raw_mut_impl(this);
/// (
/// ret.0.map(|x|&mut *x),
/// ret.1.map(|x|&mut *x),
/// )
/// }
/// }
///
/// unsafe fn rev_get_multi_field_raw_mut_impl(
/// self,
/// this: *mut [T]
/// ) -> Self::UnnormFieldsRawMut{
/// (
/// get_at_raw(this, self.first() ),
/// get_at_raw(this, self.second()),
/// )
/// }
/// }
///
/// /// # Safety
/// ///
/// /// The passed in `*mut [T]` must point to fully initialized memory.
/// ///
/// /// The index that you pass in must not have already been borrowed.
/// unsafe fn get_at_raw<T>(this: *mut [T], index: usize)-> Result<*mut T, FailedAccess> {
/// // There might be a better way to get the length of a `*mut [T]`.
/// let len=(*this).len();
///
/// if index < len {
/// Ok(&mut *(this as *mut T).add(index) as *mut T)
/// } else {
/// Err(FailedAccess)
/// }
/// }
///
///
/// ```
///
pub unsafe
/// Gets mutable references to multiple fields from `This`,
/// usually a tuple of `Option<&mut _>`s and `&mut _`s.
///
/// This trait has a blanket implementation for the [`RevGetMultiFieldMutImpl`] trait,
/// implementing that trait is necessary to be able to use this trait.
///
/// This is used by the
/// [`StructuralExt::fields_mut`](../../trait.StructuralExt.html#method.fields_mut)
/// method.
///
/// There's also the [`RevGetMultiFieldMutOut`] type alias to get this trait's
/// [`FieldsMut`] associated type.
///
/// # Example
///
/// This demonstrates using `RevGetMultiFieldMut` with structs.
///
/// ```rust
/// use structural::{StructuralExt, FP, fp};
/// use structural::field::RevGetMultiFieldMut;
/// use structural::for_examples::{Tuple2, Tuple3};
///
/// use std::cmp::Ordering;
///
/// fn access_fields<'a,T,O0,O1>(this: &'a mut T)->(&'a mut O0,&'a mut O1)
/// where
/// // The `FieldsMut= (&'a mut O0,&'a mut O1)` constraint ensures that
/// // the return type is a pair.
/// FP!(0,1): RevGetMultiFieldMut<'a,T,FieldsMut= (&'a mut O0,&'a mut O1)>
/// {
/// this.fields_mut(fp!(0,1))
/// }
///
/// let mut tup2 = Tuple2(Some(8), Ordering::Less);
/// let mut tup3 = Tuple3(Some("hello"), Some(true), 34);
///
/// assert_eq!( access_fields(&mut tup2), (&mut Some(8), &mut Ordering::Less) );
/// assert_eq!( access_fields(&mut tup3), (&mut Some("hello"), &mut Some(true)) );
///
/// ```
///
/// # Example
///
/// This demonstrates how you can use `RevGetMultiFieldMut` with enums.
///
/// ```rust
/// use structural::{StructuralExt, field_path_aliases};
/// use structural::field::{RevGetMultiFieldMut,RevGetMultiFieldMutOut};
/// use structural::for_examples::{Bomb, WithBoom};
///
/// use std::cmp::Ordering;
///
/// // Using the `field_path_aliases` macro is required to declare the `ThePath` constant,
/// // since it's unsafe to construct paths for borrowing multiple fields mutably
/// // (the macro ensures that they alias doesn't refer to the same field multiple times).
/// field_path_aliases!{
/// ThePath=(::Boom=>a,b),
/// }
/// fn access_fields<'a,T,O0,O1>(this: &'a mut T)->Option<(&'a mut O0,&'a mut O1)>
/// where
/// // The `FieldsMut= Option<(&'a mut O0,&'a mut O1)>` constraint ensures that
/// // the return type is an optional pair.
/// ThePath: RevGetMultiFieldMut<'a,T,FieldsMut= Option<(&'a mut O0,&'a mut O1)>>
/// {
/// this.fields_mut(ThePath)
/// }
///
/// fn main(){
/// let mut with_0 = WithBoom::Nope;
/// let mut with_1 = WithBoom::Boom{a:"hi", b: &[0,1,2]};
/// assert_eq!( access_fields(&mut with_0), None );
/// assert_eq!( access_fields(&mut with_1), Some((&mut "hi", &mut &[0,1,2][..])) );
///
/// let mut bomb_0 = Bomb::Nope;
/// let mut bomb_1 = Bomb::Boom{a:"hello", b: &[5,8,13]};
/// assert_eq!( access_fields(&mut bomb_0), None );
/// assert_eq!( access_fields(&mut bomb_1), Some((&mut "hello", &mut &[5,8,13][..])) );
/// }
///
/// ```
///
/// [`RevGetMultiFieldMutOut`]: ./type.RevGetMultiFieldMutOut.html
///
/// [`RevGetMultiFieldMutImpl`]: ./trait.RevGetMultiFieldMutImpl.html
///
/// [`FieldsMut`]: ./trait.RevGetMultiFieldMut.html#associatedtype.FieldsMut
///
/// [`RevGetMultiFieldImpl::rev_get_multi_field`]:
/// ./trait.RevGetMultiFieldImpl.html#tymethod.rev_get_multi_field
////////////////////////////////////////////////////////////////////////////////
/// Converts `This` into multiple fields by value,
/// usually returning a tuple of `Result<T, E: IsFieldErr>`s,
///
/// `This` is the type we are accessing,and `Self` is a field path.
///
/// To get `Option<T>`s and `T`s instead of each of those `Result`s,
/// you can use the [`RevIntoMultiField`] as a bound instead.
///
/// <span id="implementation-example"></span>
/// # Example: implementation
///
/// This example demonstrates how you can implement this trait by delegating to
/// implementations of `RevMoveOutFieldImpl` known not to alias.
///
/// ```rust
/// use structural::{FP, make_struct};
/// use structural::for_examples::{Struct2, Struct3};
/// use structural::path::{IsMultiFieldPath, UniquePaths};
/// use structural::field::{
/// ownership::IntoFieldsWrapper,
/// DropFields, IsFieldErr, NormalizeFields,
/// RevIntoMultiFieldImpl, RevIntoMultiFieldOut, RevIntoMultiField, RevMoveOutFieldImpl
/// };
///
/// let value_0=Struct2{foo: Some(5), bar: 8};
/// assert_eq!(into_foo_bar(value_0), (Some(5), 8));
///
/// let value_1=Struct3{foo: Some(13), bar: 21, baz: 34};
/// assert_eq!(into_foo_bar(value_1), (Some(13), 21));
///
/// fn into_foo_bar<T>(this: T)->RevIntoMultiFieldOut<FooBarPair, T>
/// where
/// FooBarPair: RevIntoMultiField<T>,
/// {
/// FooBarPair.rev_into_multi_field(this)
/// }
///
///
/// struct FooBarPair;
///
/// type Foo_P=FP!(foo);
/// type Bar_P=FP!(bar);
///
/// impl IsMultiFieldPath for FooBarPair{
/// type PathUniqueness = UniquePaths;
/// }
///
/// impl<T0,T1,E0,E1,This> RevIntoMultiFieldImpl<This> for FooBarPair
/// where
/// This: DropFields,
/// Foo_P: RevMoveOutFieldImpl<This, Ty=T0, Err=E0>,
/// Bar_P: RevMoveOutFieldImpl<This, Ty=T1, Err=E1>,
/// E0: IsFieldErr,
/// E1: IsFieldErr,
/// (
/// Result<T0, E0>,
/// Result<T1, E1>,
/// ): NormalizeFields
/// {
/// type UnnormIntoFields=(
/// Result<T0, E0>,
/// Result<T1, E1>,
/// );
///
/// fn rev_into_multi_field_impl(self, this: This) -> Self::UnnormIntoFields{
/// // This is unsafe because:
/// //
/// // - The `moved: &mut MovedOutFields` passed to `rev_move_out_field` must only
/// // be mutated inside of `rev_move_out_field`
/// //
/// // - `rev_move_out_field` must be called only once for any given field,
/// // since calling it twice would move a field twice.
/// unsafe{
/// let mut this=IntoFieldsWrapper::new(this);
///
/// let (this, moved)=this.inner_and_moved_mut();
/// (
/// <Foo_P>::NEW.rev_move_out_field(this, moved),
/// <Bar_P>::NEW.rev_move_out_field(this, moved),
/// )
/// }
/// }
/// }
///
/// ```
///
/// [`RevIntoMultiField`]: ./trait.RevIntoMultiField.html
///
///
/// Converts `This` into multiple fields by value.
///
/// This trait has a blanket implementation for the [`RevIntoMultiFieldImpl`] trait,
/// implementing that trait is necessary to be able to use this trait.
///
/// This is used by the
/// [`StructuralExt::into_fields`](../../trait.StructuralExt.html#method.into_fields)
/// method.
///
/// There's also the [`RevIntoMultiFieldOut`] type alias to get this trait's
/// [`IntoFields`] associated type.
///
/// # Example
///
/// This demonstrates how you can use `RevIntoMultiField` with structs.
///
/// ```rust
/// use structural::{
/// field::RevIntoMultiField,
/// for_examples::{Tuple3, Tuple4},
/// FP, StructuralExt, fp,
/// };
///
/// assert_eq!(into_pair((13,21,34)), (13,21));
///
/// assert_eq!(into_pair(('a','b','c','d','e')), ('a','b'));
///
/// assert_eq!(into_pair(Tuple3(Some(3),5,8)), (Some(3),5));
///
/// assert_eq!(into_pair(Tuple4(Some("foo"),"bar","baz","qux")), (Some("foo"),"bar"));
///
/// fn into_pair<A,B,T>(this: T)->(A,B)
/// where
/// FP!(0,1): RevIntoMultiField<T,IntoFields= (A,B)>,
/// {
/// this.into_fields(fp!(0,1))
/// }
///
/// ```
///
/// # Example
///
/// This demonstrates how you can use `RevIntoMultiField` with enums.
///
/// ```rust
/// use structural::{
/// field::RevIntoMultiField,
/// for_examples::{Bomb, WithBoom},
/// FP, StructuralExt, fp,
/// };
///
/// let with_0 = WithBoom::Nope;
/// let with_1 = WithBoom::Boom{a:"hi", b: &[0,1,2]};
/// assert_eq!( into_pair(with_0), None );
/// assert_eq!( into_pair(with_1), Some(("hi", &[0,1,2][..])) );
///
/// let bomb_0 = Bomb::Nope;
/// let bomb_1 = Bomb::Boom{a:"hello", b: &[5,8,13]};
/// assert_eq!( into_pair(bomb_0), None );
/// assert_eq!( into_pair(bomb_1), Some(("hello", &[5,8,13][..])) );
///
/// fn into_pair<A,B,T>(this: T)->Option<(A,B)>
/// where
/// FP!(::Boom=>a,b): RevIntoMultiField<T,IntoFields= Option<(A,B)>>,
/// {
/// this.into_fields(fp!(::Boom=>a,b))
/// }
///
/// ```
///
/// [`RevIntoMultiFieldOut`]: ./type.RevIntoMultiFieldOut.html
///
/// [`RevIntoMultiFieldImpl`]: ./trait.RevIntoMultiFieldImpl.html
///
/// [`FieldsMut`]: ./trait.RevIntoMultiField.html#associatedtype.FieldsMut
///
/// [`IntoFields`]: ./trait.RevIntoMultiField.html#associatedtype.IntoFields
///
////////////////////////////////////////////////////////////////////////////////
/// Moves out mutiple fields from `This`.
///
/// This is used by implementors of the [`RevIntoMultiFieldImpl`] trait from 9 up to 64 fields.
///
/// # Safety
///
/// Implementors must ensure that all the fields moved out of `This` are unique,
/// meaning that no field is moved out more than once.
pub unsafe