1use smol_str::SmolStr;
2
3pub fn object_ref_matches_table(
4 possible_references: &[Vec<SmolStr>],
5 targets: &[Vec<SmolStr>],
6) -> bool {
7 if possible_references.is_empty() {
9 return true;
10 }
11
12 let strip_quotes = |s: &str| s.trim_matches('"').to_string();
14
15 for pr in possible_references {
17 for t in targets {
18 if pr.len() == t.len()
19 && pr
20 .iter()
21 .zip(t.iter())
22 .all(|(p, t)| strip_quotes(p.as_str()) == strip_quotes(t.as_str()))
23 {
24 return true;
25 }
26 }
27 }
28
29 for pr in possible_references {
31 for t in targets {
32 if pr.len() == 1
34 && t.len() == 1
35 && strip_quotes(pr[0].as_str()) == strip_quotes(t[0].as_str())
36 {
37 return true;
38 }
39 if pr.len() == 2
41 && t.len() == 1
42 && strip_quotes(pr[1].as_str()) == strip_quotes(t[0].as_str())
43 {
44 return true;
45 }
46 }
47 }
48
49 for pr in possible_references {
51 for t in targets {
52 match pr.len().cmp(&t.len()) {
53 std::cmp::Ordering::Less => {
54 let suffix_match = pr
55 .iter()
56 .zip(t[t.len() - pr.len()..].iter())
57 .all(|(p, t)| strip_quotes(p.as_str()) == strip_quotes(t.as_str()));
58 if suffix_match {
59 return true;
60 }
61 }
62 std::cmp::Ordering::Greater => {
63 let suffix_match = t
64 .iter()
65 .zip(pr[pr.len() - t.len()..].iter())
66 .all(|(t, p)| strip_quotes(t.as_str()) == strip_quotes(p.as_str()));
67 if suffix_match {
68 return true;
69 }
70 }
71 std::cmp::Ordering::Equal => {}
72 }
73 }
74 }
75
76 false
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_object_ref_matches_table() {
85 let test_cases = vec![
86 (vec![], vec![vec!["abc".into()]], true),
88 (
90 vec![vec!["agent1".into()]],
91 vec![vec!["agent1".into()]],
92 true,
93 ),
94 (
95 vec![vec!["agent1".into()]],
96 vec![vec!["customer".into()]],
97 false,
98 ),
99 (
101 vec![vec!["bar".into()], vec!["user_id".into()]],
102 vec![vec!["bar".into()]],
103 true,
104 ),
105 (
106 vec![vec!["foo".into()], vec!["user_id".into()]],
107 vec![vec!["bar".into()]],
108 false,
109 ),
110 (
112 vec![vec!["table1".into()]],
113 vec![
114 vec!["table1".into()],
115 vec!["table2".into()],
116 vec!["table3".into()],
117 ],
118 true,
119 ),
120 (
121 vec![vec!["tbl2".into()]],
122 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
123 false,
124 ),
125 (
126 vec![vec!["tbl2".into()]],
127 vec![vec!["db".into(), "sc".into(), "tbl2".into()]],
128 true,
129 ),
130 (
132 vec![vec!["Arc".into(), "tbl1".into()]],
133 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
134 false,
135 ),
136 (
137 vec![vec!["sc".into(), "tbl1".into()]],
138 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
139 true,
140 ),
141 (
142 vec![vec!["cb".into(), "sc".into(), "tbl1".into()]],
143 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
144 false,
145 ),
146 (
147 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
148 vec![vec!["db".into(), "sc".into(), "tbl1".into()]],
149 true,
150 ),
151 (
152 vec![vec!["public".into(), "agent1".into()]],
153 vec![vec!["agent1".into()]],
154 true,
155 ),
156 (
157 vec![vec!["public".into(), "agent1".into()]],
158 vec![vec!["public".into()]],
159 false,
160 ),
161 ];
162
163 for (possible_references, targets, expected) in test_cases {
164 assert_eq!(
165 object_ref_matches_table(&possible_references, &targets),
166 expected
167 );
168 }
169 }
170}