-
-
Notifications
You must be signed in to change notification settings - Fork 207
/
in.ex
78 lines (64 loc) · 1.9 KB
/
in.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
defmodule Ash.Query.Operator.In do
@moduledoc """
left in [1, 2, 3]
this predicate matches if the left is in the list on the right
For comparison, this simplifies to a set of "or equals", e.g
`{:or, {:or, {:or, left == 1}, left == 2}, left == 3}`
"""
use Ash.Query.Operator,
operator: :in,
predicate?: true,
types: [[:any, {:array, :same}]]
@inspect_items_limit 10
@dialyzer {:nowarn_function, compare: 2}
def new(%Ash.Query.Ref{} = left, right) when is_list(right) do
{:ok, %__MODULE__{left: left, right: MapSet.new(right)}}
end
def new(left, right), do: {:ok, %__MODULE__{left: left, right: right}}
def evaluate(%{left: left, right: right}) do
{:known, Enum.any?(right, &Comp.equal?(&1, left))}
end
def compare(%__MODULE__{left: left, right: %MapSet{} = left_right}, %__MODULE__{
left: left,
right: %MapSet{} = right_right
}) do
if MapSet.equal?(left_right, right_right) do
:mutually_inclusive
else
if MapSet.disjoint?(left_right, right_right) do
:mutually_exclusive
else
:unknown
end
end
end
def compare(%__MODULE__{}, %Ash.Query.Operator.Eq{
right: %Ref{}
}),
do: false
def compare(%__MODULE__{left: left, right: %MapSet{} = left_right}, %Ash.Query.Operator.Eq{
left: left,
right: value
}) do
if MapSet.member?(left_right, value) do
:left_implies_right
else
:mutually_exclusive
end
end
def compare(_, _), do: :unknown
def to_string(%{right: %Ref{}} = op, opts), do: super(op, opts)
def to_string(%{left: left, right: mapset}, opts) do
import Inspect.Algebra
list_doc =
case Enum.split(mapset, @inspect_items_limit) do
{left, []} -> to_doc(left, opts)
{left, _} -> concat(to_doc(left, opts), "...")
end
concat([
to_doc(left, opts),
" in ",
list_doc
])
end
end