1use crate::{ColumnTrait, EntityTrait, IdenStatic};
2use sea_query::{Alias, DynIden, Iden, IntoIden, SeaRc};
3use std::{borrow::Cow, fmt::Write};
4
5#[derive(Debug, Clone, Hash)]
7pub enum Identity {
8 Unary(DynIden),
10 Binary(DynIden, DynIden),
12 Ternary(DynIden, DynIden, DynIden),
14 Many(Vec<DynIden>),
16}
17
18impl Identity {
19 pub fn arity(&self) -> usize {
21 match self {
22 Self::Unary(_) => 1,
23 Self::Binary(_, _) => 2,
24 Self::Ternary(_, _, _) => 3,
25 Self::Many(vec) => vec.len(),
26 }
27 }
28
29 pub fn iter(&self) -> BorrowedIdentityIter<'_> {
31 BorrowedIdentityIter {
32 identity: self,
33 index: 0,
34 }
35 }
36}
37
38impl IntoIterator for Identity {
39 type Item = DynIden;
40 type IntoIter = OwnedIdentityIter;
41
42 fn into_iter(self) -> Self::IntoIter {
43 OwnedIdentityIter {
44 identity: self,
45 index: 0,
46 }
47 }
48}
49
50impl Iden for Identity {
51 fn quoted(&self) -> Cow<'static, str> {
52 match self {
53 Identity::Unary(iden) => iden.inner(),
54 Identity::Binary(iden1, iden2) => Cow::Owned(format!("{iden1}{iden2}")),
55 Identity::Ternary(iden1, iden2, iden3) => Cow::Owned(format!("{iden1}{iden2}{iden3}")),
56 Identity::Many(vec) => {
57 let mut s = String::new();
58 for iden in vec.iter() {
59 write!(&mut s, "{iden}").expect("Infallible");
60 }
61 Cow::Owned(s)
62 }
63 }
64 }
65
66 fn to_string(&self) -> String {
67 match self.quoted() {
68 Cow::Borrowed(s) => s.to_owned(),
69 Cow::Owned(s) => s,
70 }
71 }
72
73 fn unquoted(&self) -> &str {
74 panic!("Should not call this")
75 }
76}
77
78#[derive(Debug)]
80pub struct BorrowedIdentityIter<'a> {
81 identity: &'a Identity,
82 index: usize,
83}
84
85#[derive(Debug)]
87pub struct OwnedIdentityIter {
88 identity: Identity,
89 index: usize,
90}
91
92impl<'a> Iterator for BorrowedIdentityIter<'a> {
93 type Item = &'a DynIden;
94
95 fn next(&mut self) -> Option<Self::Item> {
96 let result = match self.identity {
97 Identity::Unary(iden1) => {
98 if self.index == 0 {
99 Some(iden1)
100 } else {
101 None
102 }
103 }
104 Identity::Binary(iden1, iden2) => match self.index {
105 0 => Some(iden1),
106 1 => Some(iden2),
107 _ => None,
108 },
109 Identity::Ternary(iden1, iden2, iden3) => match self.index {
110 0 => Some(iden1),
111 1 => Some(iden2),
112 2 => Some(iden3),
113 _ => None,
114 },
115 Identity::Many(vec) => vec.get(self.index),
116 };
117 self.index += 1;
118 result
119 }
120}
121
122impl Iterator for OwnedIdentityIter {
123 type Item = DynIden;
124
125 fn next(&mut self) -> Option<Self::Item> {
126 let result = match &self.identity {
127 Identity::Unary(iden1) => {
128 if self.index == 0 {
129 Some(iden1.clone())
130 } else {
131 None
132 }
133 }
134 Identity::Binary(iden1, iden2) => match self.index {
135 0 => Some(iden1.clone()),
136 1 => Some(iden2.clone()),
137 _ => None,
138 },
139 Identity::Ternary(iden1, iden2, iden3) => match self.index {
140 0 => Some(iden1.clone()),
141 1 => Some(iden2.clone()),
142 2 => Some(iden3.clone()),
143 _ => None,
144 },
145 Identity::Many(vec) => vec.get(self.index).cloned(),
146 };
147 self.index += 1;
148 result
149 }
150}
151
152pub trait IntoIdentity {
154 fn into_identity(self) -> Identity;
156}
157
158pub trait IdentityOf<E>
160where
161 E: EntityTrait,
162{
163 fn identity_of(self) -> Identity;
165}
166
167impl IntoIdentity for Identity {
168 fn into_identity(self) -> Identity {
169 self
170 }
171}
172
173impl IntoIdentity for String {
174 fn into_identity(self) -> Identity {
175 self.as_str().into_identity()
176 }
177}
178
179impl IntoIdentity for &str {
180 fn into_identity(self) -> Identity {
181 Identity::Unary(SeaRc::new(Alias::new(self)))
182 }
183}
184
185impl<T> IntoIdentity for T
186where
187 T: IdenStatic,
188{
189 fn into_identity(self) -> Identity {
190 Identity::Unary(self.into_iden())
191 }
192}
193
194impl<T, C> IntoIdentity for (T, C)
195where
196 T: IdenStatic,
197 C: IdenStatic,
198{
199 fn into_identity(self) -> Identity {
200 Identity::Binary(self.0.into_iden(), self.1.into_iden())
201 }
202}
203
204impl<T, C, R> IntoIdentity for (T, C, R)
205where
206 T: IdenStatic,
207 C: IdenStatic,
208 R: IdenStatic,
209{
210 fn into_identity(self) -> Identity {
211 Identity::Ternary(self.0.into_iden(), self.1.into_iden(), self.2.into_iden())
212 }
213}
214
215macro_rules! impl_into_identity {
216 ( $($T:ident : $N:tt),+ $(,)? ) => {
217 impl< $($T),+ > IntoIdentity for ( $($T),+ )
218 where
219 $($T: IdenStatic),+
220 {
221 fn into_identity(self) -> Identity {
222 Identity::Many(vec![
223 $(self.$N.into_iden()),+
224 ])
225 }
226 }
227 };
228}
229
230#[rustfmt::skip]
231mod impl_into_identity {
232 use super::*;
233
234 impl_into_identity!(T0:0, T1:1, T2:2, T3:3);
235 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4);
236 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
237 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
238 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
239 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
240 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
241 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10);
242 impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10, T11:11);
243}
244
245impl<E, C> IdentityOf<E> for C
246where
247 E: EntityTrait<Column = C>,
248 C: ColumnTrait,
249{
250 fn identity_of(self) -> Identity {
251 self.into_identity()
252 }
253}
254
255macro_rules! impl_identity_of {
256 ( $($T:ident),+ $(,)? ) => {
257 impl<E, C> IdentityOf<E> for ( $($T),+ )
258 where
259 E: EntityTrait<Column = C>,
260 C: ColumnTrait,
261 {
262 fn identity_of(self) -> Identity {
263 self.into_identity()
264 }
265 }
266 };
267}
268
269#[rustfmt::skip]
270mod impl_identity_of {
271 use super::*;
272
273 impl_identity_of!(C, C);
274 impl_identity_of!(C, C, C);
275 impl_identity_of!(C, C, C, C);
276 impl_identity_of!(C, C, C, C, C);
277 impl_identity_of!(C, C, C, C, C, C);
278 impl_identity_of!(C, C, C, C, C, C, C);
279 impl_identity_of!(C, C, C, C, C, C, C, C);
280 impl_identity_of!(C, C, C, C, C, C, C, C, C);
281 impl_identity_of!(C, C, C, C, C, C, C, C, C, C);
282 impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C);
283 impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C, C);
284}