Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(variadics): add traits for dealing with variadics of references #1324

Merged
merged 9 commits into from
Jul 2, 2024
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 159 additions & 15 deletions variadics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,28 @@ pub trait VariadicExt: Variadic {
fn reverse(self) -> Self::Reverse;

/// This as a variadic of references.
type AsRefVar<'a>: Copy + Variadic
type AsRefVar<'a>: RefVariadic<UnRef = Self>
where
Self: 'a;
/// Convert a reference to this variadic into a variadic of references.
/// ```rust
/// # use variadics::*;
/// let as_ref: var_type!(&u32, &String, &bool) =
/// var_expr!(1_u32, "Hello".to_owned(), false).as_ref_var();
/// ```
fn as_ref_var(&self) -> Self::AsRefVar<'_>;

/// This as a variadic of exclusive (`mut`) references.
type AsMutVar<'a>: Variadic
type AsMutVar<'a>: MutVariadic<UnMut = Self>
where
Self: 'a;
/// Convert an exclusive (`mut`) reference to this variadic into a variadic of exclusive
/// (`mut`) references.
/// ```rust
/// # use variadics::*;
/// let as_mut: var_type!(&mut u32, &mut String, &mut bool) =
/// var_expr!(1_u32, "Hello".to_owned(), false).as_mut_var();
/// ```
fn as_mut_var(&mut self) -> Self::AsMutVar<'_>;

/// Iterator type returned by [`Self::iter_any_ref`].
Expand Down Expand Up @@ -263,32 +273,166 @@ impl VariadicExt for () {
}
}

/// Convert from a variadic of references back into the original variadic. The inverse of
/// [`VariadicExt::as_ref_var`] or [`VariadicExt::as_mut_var`].
/// A variadic where each item is a shared reference `&item`.
///
/// This can be created using [`VariadicExt::as_ref_var`]:
/// ```rust
/// # use variadics::*;
/// let as_ref: var_type!(&u32, &String, &bool) =
/// var_expr!(1_u32, "Hello".to_owned(), false).as_ref_var();
/// ```
///
/// This is a sealed trait.
#[sealed]
pub trait UnrefVariadic: Variadic {
/// The un-referenced variadic. Each item will have one layer of references removed.
type Unref: VariadicExt;
pub trait RefVariadic: Variadic
where
Self: Copy,
{
/// The un-referenced variadic. Each item will have one layer of shared references removed.
MingweiSamuel marked this conversation as resolved.
Show resolved Hide resolved
///
/// The inverse of [`VariadicExt::AsRefVar`].
///
/// ```rust
/// # use variadics::*;
/// let un_ref: <var_type!(&u32, &String, &bool) as RefVariadic>::UnRef =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no way to make this a method call so it rhymes with the other things here?

/// var_expr!(1_u32, "Hello".to_owned(), false);
/// ```
type UnRef: VariadicExt;
}
#[sealed]
impl<Item, Rest> RefVariadic for (&Item, Rest)
where
Rest: RefVariadic,
{
type UnRef = (Item, Rest::UnRef);
}
#[sealed]
impl RefVariadic for () {
type UnRef = ();
}

/// A variadic where each item is an exclusive reference `&mut item`.
///
/// This can be created using [`VariadicExt::as_mut_var`]:
/// ```rust
/// # use variadics::*;
/// let as_mut: var_type!(&mut u32, &mut String, &mut bool) =
/// var_expr!(1_u32, "Hello".to_owned(), false).as_mut_var();
/// ```
///
/// This is a sealed trait.
#[sealed]
pub trait MutVariadic: Variadic {
/// The un-referenced variadic. Each item will have one layer of exclusive references removed.
///
MingweiSamuel marked this conversation as resolved.
Show resolved Hide resolved
/// The inverse of [`VariadicExt::AsMutVar`].
///
/// ```rust
/// # use variadics::*;
/// let un_mut: <var_type!(&mut u32, &mut String, &mut bool) as MutVariadic>::UnMut =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment to unref

/// var_expr!(1_u32, "Hello".to_owned(), false);
/// ```
type UnMut: VariadicExt;

/// Type returned by [`Self::downgrade`].
type Downgrade: RefVariadic<UnRef = Self::UnMut>;
/// Downgrade this to a variadic of shared reference [`RefVariadic`].
///
/// ```rust
/// # use variadics::*;
/// let mut original = var_expr!(1_u32, "Hello".to_owned(), false);
/// let as_mut: var_type!(&mut u32, &mut String, &mut bool) = original.as_mut_var();
/// let as_ref_1: var_type!(&u32, &String, &bool) = as_mut.downgrade();
/// let as_ref_2: var_type!(&u32, &String, &bool) = as_ref_1; // Can copy the reference version.
MingweiSamuel marked this conversation as resolved.
Show resolved Hide resolved
/// drop((as_ref_1, as_ref_2));
/// ```
fn downgrade(self) -> Self::Downgrade;
}
#[sealed]
impl<'a, Item, Rest> MutVariadic for (&'a mut Item, Rest)
where
Rest: MutVariadic,
{
type UnMut = (Item, Rest::UnMut);

type Downgrade = (&'a Item, Rest::Downgrade);
fn downgrade(self) -> Self::Downgrade {
let var_args!(item, ...rest) = self;
var_expr!(&*item, ...rest.downgrade())
}
}
#[sealed]
impl MutVariadic for () {
type UnMut = ();

type Downgrade = ();
fn downgrade(self) -> Self::Downgrade {}
}

#[sealed]
/// Clone an [`RefVariadic`] into an [`RefVariadic::UnRef`] variadic of owned values.
pub trait CloneRefVariadic: RefVariadic {
/// Clone self per-value.
fn clone_var(&self) -> Self::UnRef;
}
#[sealed]
impl<Item, Rest> UnrefVariadic for (&Item, Rest)
impl<Item, Rest> CloneRefVariadic for (&Item, Rest)
where
Rest: UnrefVariadic,
Item: Clone,
Rest: CloneRefVariadic,
{
type Unref = (Item, Rest::Unref);
fn clone_var(&self) -> Self::UnRef {
let var_args!(item, ...rest) = self;
var_expr!((*item).clone(), ...rest.clone_var())
}
}
#[sealed]
impl<Item, Rest> UnrefVariadic for (&mut Item, Rest)
impl CloneRefVariadic for () {
fn clone_var(&self) -> Self::UnRef {}
}

/// A variadic where all item implement `PartialEq`.
#[sealed]
pub trait PartialEqVariadic: VariadicExt {
/// `PartialEq` between a referenced variadic and a variadic of references, of the same types.
fn eq(&self, other: &Self) -> bool;

/// `PartialEq` for the `AsRefVar` version op `Self`.
fn eq_ref<'a>(this: Self::AsRefVar<'a>, other: Self::AsRefVar<'a>) -> bool;
}
#[sealed]
impl<Item, Rest> PartialEqVariadic for (Item, Rest)
where
Rest: UnrefVariadic,
Item: PartialEq,
Rest: PartialEqVariadic,
{
type Unref = (Item, Rest::Unref);
fn eq(&self, other: &Self) -> bool {
let var_args!(item_self, ...rest_self) = self;
let var_args!(item_other, ...rest_other) = other;
item_self == item_other && rest_self.eq(rest_other)
}

fn eq_ref<'a>(
this: <Self as VariadicExt>::AsRefVar<'a>,
other: <Self as VariadicExt>::AsRefVar<'a>,
) -> bool {
let var_args!(item_self, ...rest_self) = this;
let var_args!(item_other, ...rest_other) = other;
item_self == item_other && Rest::eq_ref(rest_self, rest_other)
}
}
#[sealed]
impl UnrefVariadic for () {
type Unref = ();
impl PartialEqVariadic for () {
fn eq(&self, _other: &Self) -> bool {
true
}

fn eq_ref<'a>(
_this: <Self as VariadicExt>::AsRefVar<'a>,
_other: <Self as VariadicExt>::AsRefVar<'a>,
) -> bool {
true
}
}

/// A variadic where all elements are the same type, `T`.
Expand Down
Loading