yewtil/not_equal_assign.rs
1//! Module for `neq_assign` utility function.
2
3use std::borrow::BorrowMut;
4use yew::html::ShouldRender;
5
6/// Blanket trait to provide a convenience method for assigning props in `changed` or updating values in `update`.
7pub trait NeqAssign<NEW> {
8 /// If `self` and `new` aren't equal, assigns `new` to `self` and returns true, otherwise returns false.
9 ///
10 /// Short for "Not equal assign".
11 ///
12 /// # Example
13 /// ```
14 /// # use yew::{Component, ShouldRender, ComponentLink};
15 /// # use yewtil::NeqAssign;
16 /// # use yew::Properties;
17 ///# use yew::virtual_dom::VNode;
18 /// ##[derive(Clone, Properties, PartialEq)]
19 /// struct Props {
20 /// field1: String,
21 /// field2: usize
22 /// }
23 /// struct Model {
24 /// props: Props
25 /// }
26 /// impl Component for Model {
27 /// # type Message = ();
28 /// type Properties = Props;
29 /// // ...
30 /// #
31 /// # fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
32 /// # unimplemented!()
33 /// # }
34 /// # fn update(&mut self, msg: ()) -> ShouldRender {
35 /// # unimplemented!()
36 /// # }
37 /// #
38 /// fn change(&mut self, props: Self::Properties) -> ShouldRender{
39 /// self.props.neq_assign(props)
40 /// }
41 ///#
42 ///# fn view(&self) -> VNode {
43 ///# unimplemented!()
44 ///# }
45 /// }
46 ///
47 /// let mut foo = 1;
48 ///
49 /// assert_eq!(foo.neq_assign(42), true);
50 /// assert_eq!(foo, 42);
51 ///
52 /// assert_eq!(foo.neq_assign(42), false);
53 /// ```
54 fn neq_assign(&mut self, new: NEW) -> ShouldRender;
55}
56
57impl<T: BorrowMut<U>, U: PartialEq> NeqAssign<U> for T {
58 fn neq_assign(&mut self, new: U) -> bool {
59 self.neq_assign_by(new, |x, y| x == y)
60 }
61}
62/// Blanket trait to provide a convenience method for assigning props in `changed` or updating values in `update`.
63///
64/// Like `neq_assign`, but for cases where `self` doesn't impl `PartialEq` or a nonstandard equality comparison is needed.
65///
66/// Useful for `Result<T, E: !PartialEq>`.
67pub trait NeqAssignBy<NEW> {
68 /// ```
69 /// # use yewtil::{NeqAssign, NeqAssignBy};
70 /// ##[derive(Clone, Debug)]
71 /// struct NonComparableError;
72 ///
73 /// fn eq_by_ok<T, E>(a: &Result<T, E>, b: &Result<T, E>) -> bool
74 /// where
75 /// T: PartialEq,
76 /// {
77 /// match (a, b) {
78 /// (Ok(_), Err(_))
79 /// | (Err(_), Ok(_))
80 /// | (Err(_), Err(_)) => false,
81 /// (Ok(a), Ok(b)) => a == b,
82 /// }
83 /// }
84 ///
85 /// let mut foo: Result<u32, NonComparableError> = Ok(1);
86 ///
87 /// // Won't compile
88 /// // assert_eq!(foo.neq_assign(Ok(42)), true)
89 ///
90 /// assert_eq!(foo.neq_assign_by(Ok(42), eq_by_ok), true);
91 /// assert_eq!(foo.clone().unwrap(), 42);
92 ///
93 /// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
94 /// assert!(foo.is_err());
95 ///
96 /// // The tradeoff: all assignments of an `Err` value will count as updates, even if they are
97 /// // "the same" for all practical intents and purposes.
98 /// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
99 /// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
100 /// assert_eq!(foo.neq_assign_by(Err(NonComparableError), eq_by_ok), true);
101 /// ```
102 ///
103 fn neq_assign_by<F>(&mut self, new: NEW, eq: F) -> ShouldRender
104 where
105 F: FnOnce(&NEW, &NEW) -> bool;
106}
107
108impl<T: BorrowMut<U>, U> NeqAssignBy<U> for T {
109 fn neq_assign_by<F>(&mut self, new: U, eq: F) -> ShouldRender
110 where
111 F: FnOnce(&U, &U) -> bool,
112 {
113 if !eq(self.borrow(), &new) {
114 *self.borrow_mut() = new;
115 true
116 } else {
117 false
118 }
119 }
120}