Added `NeqAssignBy` trait (#1389)

Similar to `NeqAssign`, but accepts a `FnOnce(&U, &U) -> bool` to perform equality comparison instead of relying on `PartialEq` impl
Reimplemented `NeqAssign` in terms of `NeqAssignBy`
Added doctests for both traits

Co-authored-by: EndilWayfare <p.rochendil@gmail.com>
This commit is contained in:
EndilWayfare 2020-07-10 02:47:40 -07:00 committed by GitHub
parent 0b07709437
commit 61ed84e4aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 2 deletions

View File

@ -28,7 +28,7 @@ mod history;
pub use history::History; pub use history::History;
#[cfg(feature = "neq")] #[cfg(feature = "neq")]
pub use not_equal_assign::NeqAssign; pub use not_equal_assign::{NeqAssign, NeqAssignBy};
#[deprecated] #[deprecated]
#[cfg(feature = "pure")] #[cfg(feature = "pure")]

View File

@ -43,13 +43,74 @@ pub trait NeqAssign<NEW> {
///# unimplemented!() ///# unimplemented!()
///# } ///# }
/// } /// }
///
/// let mut foo = 1;
///
/// assert_eq!(foo.neq_assign(42), true);
/// assert_eq!(foo, 42);
///
/// assert_eq!(foo.neq_assign(42), false);
/// ``` /// ```
fn neq_assign(&mut self, new: NEW) -> ShouldRender; fn neq_assign(&mut self, new: NEW) -> ShouldRender;
} }
impl<T: BorrowMut<U>, U: PartialEq> NeqAssign<U> for T { impl<T: BorrowMut<U>, U: PartialEq> NeqAssign<U> for T {
fn neq_assign(&mut self, new: U) -> bool { fn neq_assign(&mut self, new: U) -> bool {
if self.borrow() != &new { self.neq_assign_by(new, |x, y| x == y)
}
}
/// Blanket trait to provide a convenience method for assigning props in `changed` or updating values in `update`.
///
/// Like `neq_assign`, but for cases where `self` doesn't impl `PartialEq` or a nonstandard equality comparison is needed.
///
/// Useful for `Result<T, E: !PartialEq>`.
pub trait NeqAssignBy<NEW> {
/// ```
/// # use yewtil::{NeqAssign, NeqAssignBy};
/// ##[derive(Clone, Debug)]
/// struct NonComparableError;
///
/// fn eq_by_ok<T, E>(a: &Result<T, E>, b: &Result<T, E>) -> bool
/// where
/// T: PartialEq,
/// {
/// match (a, b) {
/// (Ok(_), Err(_))
/// | (Err(_), Ok(_))
/// | (Err(_), Err(_)) => false,
/// (Ok(a), Ok(b)) => a == b,
/// }
/// }
///
/// let mut foo: Result<u32, NonComparableError> = Ok(1);
///
/// // Won't compile
/// // assert_eq!(foo.neq_assign(Ok(42)), true)
///
/// assert_eq!(foo.neq_assign_by(Ok(42), eq_by_ok), true);
/// assert_eq!(foo.clone().unwrap(), 42);
///
/// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
/// assert!(foo.is_err());
///
/// // The tradeoff: all assignments of an `Err` value will count as updates, even if they are
/// // "the same" for all practical intents and purposes.
/// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
/// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
/// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
/// ```
///
fn neq_assign_by<F>(&mut self, new: NEW, eq: F) -> ShouldRender
where
F: FnOnce(&NEW, &NEW) -> bool;
}
impl<T: BorrowMut<U>, U> NeqAssignBy<U> for T {
fn neq_assign_by<F>(&mut self, new: U, eq: F) -> ShouldRender
where
F: FnOnce(&U, &U) -> bool,
{
if !eq(self.borrow(), &new) {
*self.borrow_mut() = new; *self.borrow_mut() = new;
true true
} else { } else {