query_flow/output_eq.rs
1//! Utility functions for output equality comparison in queries.
2//!
3//! These functions are designed to be used with the `#[query(output_eq = ...)]` attribute
4//! when the output type is `Result<T, E>` and `E` does not implement `PartialEq`.
5
6/// Compare only the `Ok` values. Returns `false` for any `Err` case,
7/// causing downstream queries to be invalidated (recomputed).
8///
9/// # Example
10/// ```
11/// use query_flow::{query, Db, QueryError, QueryRuntime};
12///
13/// // Note: `MyError` deliberately has no `PartialEq`.
14/// #[derive(Debug)]
15/// struct MyError(String);
16///
17/// #[query(output_eq = query_flow::output_eq::ok_or_invalidate)]
18/// fn my_query(db: &impl Db, succeed: bool) -> Result<Result<i32, MyError>, QueryError> {
19/// let _ = db;
20/// Ok(if succeed { Ok(1) } else { Err(MyError("boom".into())) })
21/// }
22///
23/// let runtime = QueryRuntime::new();
24/// assert!(matches!(*runtime.query(MyQuery::new(true)).unwrap(), Ok(1)));
25/// assert!(matches!(*runtime.query(MyQuery::new(false)).unwrap(), Err(_)));
26/// ```
27pub fn ok_or_invalidate<T: PartialEq, E>(a: &Result<T, E>, b: &Result<T, E>) -> bool {
28 match (a, b) {
29 (Ok(a), Ok(b)) => a == b,
30 _ => false,
31 }
32}
33
34/// Compare `Ok` values for equality, treat all `Err` as equal.
35///
36/// Use this when you want to suppress downstream recomputation if both results are errors,
37/// regardless of the error content.
38///
39/// # Example
40/// ```
41/// use query_flow::{query, Db, QueryError, QueryRuntime};
42///
43/// // Note: `MyError` deliberately has no `PartialEq`.
44/// #[derive(Debug)]
45/// struct MyError(String);
46///
47/// #[query(output_eq = query_flow::output_eq::ignore_err)]
48/// fn my_query(db: &impl Db, succeed: bool) -> Result<Result<i32, MyError>, QueryError> {
49/// let _ = db;
50/// Ok(if succeed { Ok(1) } else { Err(MyError("boom".into())) })
51/// }
52///
53/// let runtime = QueryRuntime::new();
54/// assert!(matches!(*runtime.query(MyQuery::new(false)).unwrap(), Err(_)));
55/// ```
56pub fn ignore_err<T: PartialEq, E>(a: &Result<T, E>, b: &Result<T, E>) -> bool {
57 match (a, b) {
58 (Ok(a), Ok(b)) => a == b,
59 (Err(_), Err(_)) => true,
60 _ => false,
61 }
62}