1use std::ops::Deref;
4
5use into_owned_trait::IntoOwned;
6
7use crate::{Quad, Triple};
8
9pub type TriplePattern<T, X> = Triple<Pattern<T, X>>;
12
13pub type QuadPattern<T, X> = Quad<Pattern<T, X>>;
16
17pub type LinearTriplePattern<T> = Triple<Option<T>>;
25
26impl<T> From<Triple<T>> for LinearTriplePattern<T> {
27 fn from(value: Triple<T>) -> Self {
29 value.map(Some)
30 }
31}
32
33pub type LinearQuadPattern<T> = Quad<Option<T>>;
38
39impl<T> From<Quad<T>> for LinearQuadPattern<T> {
40 fn from(value: Quad<T>) -> Self {
42 value.map(Some)
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
53pub enum Pattern<T, X> {
54 Ground(T),
56
57 Var(X),
59}
60
61impl<T, X> Pattern<T, X> {
62 pub fn as_ref(&self) -> Pattern<&T, &X> {
64 match self {
65 Self::Ground(t) => Pattern::Ground(t),
66 Self::Var(x) => Pattern::Var(x),
67 }
68 }
69
70 pub fn as_deref(&self) -> Pattern<&T::Target, &X::Target>
72 where
73 T: Deref,
74 X: Deref,
75 {
76 match self {
77 Self::Ground(t) => Pattern::Ground(t),
78 Self::Var(x) => Pattern::Var(x),
79 }
80 }
81
82 pub fn is_ground(&self) -> bool {
84 matches!(self, Self::Ground(_))
85 }
86
87 pub fn is_ground_and(&self, f: impl FnOnce(&T) -> bool) -> bool {
90 match self {
91 Self::Ground(t) => f(t),
92 Self::Var(_) => false,
93 }
94 }
95
96 pub fn is_var(&self) -> bool {
98 matches!(self, Self::Var(_))
99 }
100
101 pub fn is_var_and(&self, f: impl FnOnce(&X) -> bool) -> bool {
104 match self {
105 Self::Ground(_) => false,
106 Self::Var(x) => f(x),
107 }
108 }
109
110 pub fn is_ground_or(&self, f: impl FnOnce(&X) -> bool) -> bool {
116 match self {
117 Self::Ground(_) => true,
118 Self::Var(x) => f(x),
119 }
120 }
121
122 pub fn is_var_or(&self, f: impl FnOnce(&T) -> bool) -> bool {
128 match self {
129 Self::Ground(t) => f(t),
130 Self::Var(_) => true,
131 }
132 }
133
134 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Pattern<U, X> {
137 match self {
138 Self::Ground(t) => Pattern::Ground(f(t)),
139 Self::Var(x) => Pattern::Var(x),
140 }
141 }
142
143 pub fn map_var<Y>(self, f: impl FnOnce(X) -> Y) -> Pattern<T, Y> {
146 match self {
147 Self::Ground(t) => Pattern::Ground(t),
148 Self::Var(x) => Pattern::Var(f(x)),
149 }
150 }
151}
152
153impl<T, X> From<T> for Pattern<T, X> {
154 fn from(value: T) -> Self {
156 Self::Ground(value)
157 }
158}
159
160impl<T, X> IntoOwned for Pattern<T, X>
161where
162 T: IntoOwned,
163 X: IntoOwned,
164{
165 type Owned = Pattern<T::Owned, X::Owned>;
166
167 fn into_owned(self) -> Self::Owned {
168 match self {
169 Self::Ground(t) => Pattern::Ground(t.into_owned()),
170 Self::Var(x) => Pattern::Var(x.into_owned()),
171 }
172 }
173}
174
175impl<T, X> AsPattern for Pattern<T, X> {
176 type Ground = T;
177 type Var = X;
178
179 fn as_pattern(&self) -> Pattern<&T, &X> {
180 self.as_ref()
181 }
182}
183
184pub trait AsPattern {
191 type Ground: ?Sized;
193
194 type Var: ?Sized;
196
197 fn as_pattern(&self) -> Pattern<&Self::Ground, &Self::Var>;
199
200 fn is_ground(&self) -> bool {
202 self.as_pattern().is_ground()
203 }
204
205 fn is_ground_and(&self, f: impl FnOnce(&Self::Ground) -> bool) -> bool {
208 match self.as_pattern() {
209 Pattern::Ground(t) => f(t),
210 Pattern::Var(_) => false,
211 }
212 }
213
214 fn is_var(&self) -> bool {
216 self.as_pattern().is_var()
217 }
218
219 fn is_var_and(&self, f: impl FnOnce(&Self::Var) -> bool) -> bool {
222 match self.as_pattern() {
223 Pattern::Ground(_) => false,
224 Pattern::Var(x) => f(x),
225 }
226 }
227
228 fn is_ground_or(&self, f: impl FnOnce(&Self::Var) -> bool) -> bool {
231 match self.as_pattern() {
232 Pattern::Ground(_) => true,
233 Pattern::Var(x) => f(x),
234 }
235 }
236
237 fn is_var_or(&self, f: impl FnOnce(&Self::Ground) -> bool) -> bool {
240 match self.as_pattern() {
241 Pattern::Ground(t) => f(t),
242 Pattern::Var(_) => true,
243 }
244 }
245}