1use std::{
10 collections::{
11 hash_map::{Entry, Entry::Occupied},
12 HashMap,
13 },
14 error::Error,
15 fmt,
16};
17
18use crate::value::{convert::ToValue, Value};
19
20#[derive(Debug, Eq, PartialEq, Clone)]
22pub struct MissingNamedParameterError(pub Vec<u8>);
23
24impl fmt::Display for MissingNamedParameterError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 write!(
27 f,
28 "Missing named parameter `{}` for statement",
29 String::from_utf8_lossy(&self.0)
30 )
31 }
32}
33
34impl Error for MissingNamedParameterError {
35 fn description(&self) -> &str {
36 "Missing named parameter for statement"
37 }
38}
39
40#[derive(Clone, PartialEq)]
42pub enum Params {
43 Empty,
44 Named(HashMap<Vec<u8>, Value>),
45 Positional(Vec<Value>),
46}
47
48impl fmt::Debug for Params {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Self::Empty => write!(f, "Empty"),
52 Self::Named(arg0) => {
53 let arg0 = arg0
54 .iter()
55 .map(|(k, v)| (String::from_utf8_lossy(k), v))
56 .collect::<HashMap<_, _>>();
57 f.debug_tuple("Named").field(&arg0).finish()
58 }
59 Self::Positional(arg0) => f.debug_tuple("Positional").field(arg0).finish(),
60 }
61 }
62}
63
64impl Params {
65 pub fn into_positional(
68 self,
69 named_params: &[Vec<u8>],
70 ) -> Result<Params, MissingNamedParameterError> {
71 match self {
72 Params::Named(mut map) => {
73 let mut params: Vec<Value> = Vec::new();
74 'params: for (i, name) in named_params.iter().enumerate() {
75 match map.entry(name.clone()) {
76 Occupied(entry) => {
77 let mut x = named_params.len() - 1;
78 while x > i {
79 if *name == named_params[x] {
80 params.push(entry.get().clone());
81 continue 'params;
82 }
83 x -= 1;
84 }
85 params.push(entry.remove());
86 }
87 _ => return Err(MissingNamedParameterError(name.clone())),
88 }
89 }
90 Ok(Params::Positional(params))
91 }
92 params => Ok(params),
93 }
94 }
95}
96
97impl<'a, T: Into<Params> + Clone> From<&'a T> for Params {
98 fn from(x: &'a T) -> Params {
99 x.clone().into()
100 }
101}
102
103impl<T> From<Vec<T>> for Params
104where
105 Value: From<T>,
106{
107 fn from(x: Vec<T>) -> Params {
108 let mut raw_params: Vec<Value> = Vec::new();
109 for v in x.into_iter() {
110 raw_params.push(Value::from(v));
111 }
112 if raw_params.is_empty() {
113 Params::Empty
114 } else {
115 Params::Positional(raw_params)
116 }
117 }
118}
119
120impl<N, V> From<Vec<(N, V)>> for Params
121where
122 Vec<u8>: From<N>,
123 Value: From<V>,
124{
125 fn from(x: Vec<(N, V)>) -> Params {
126 let mut map = HashMap::default();
127 for (name, value) in x.into_iter() {
128 let name: Vec<u8> = name.into();
129 match map.entry(name) {
130 Entry::Vacant(entry) => entry.insert(Value::from(value)),
131 Entry::Occupied(entry) => {
132 panic!(
133 "Redefinition of named parameter `{}'",
134 String::from_utf8_lossy(entry.key())
135 );
136 }
137 };
138 }
139 Params::Named(map)
140 }
141}
142
143impl<'a> From<&'a [&'a dyn ToValue]> for Params {
144 fn from(x: &'a [&'a dyn ToValue]) -> Params {
145 let mut raw_params: Vec<Value> = Vec::new();
146 for v in x {
147 raw_params.push(v.to_value());
148 }
149 if raw_params.is_empty() {
150 Params::Empty
151 } else {
152 Params::Positional(raw_params)
153 }
154 }
155}
156
157impl From<()> for Params {
158 fn from(_: ()) -> Params {
159 Params::Empty
160 }
161}
162
163macro_rules! into_params_impl {
164 ($([$A:ident,$a:ident]),*) => (
165 impl<$($A: Into<Value>,)*> From<($($A,)*)> for Params {
166 fn from(x: ($($A,)*)) -> Params {
167 let ($($a,)*) = x;
168 Params::Positional(vec![
169 $($a.into(),)*
170 ])
171 }
172 }
173 );
174}
175
176into_params_impl!([A, a]);
177into_params_impl!([A, a], [B, b]);
178into_params_impl!([A, a], [B, b], [C, c]);
179into_params_impl!([A, a], [B, b], [C, c], [D, d]);
180into_params_impl!([A, a], [B, b], [C, c], [D, d], [E, e]);
181into_params_impl!([A, a], [B, b], [C, c], [D, d], [E, e], [F, f]);
182into_params_impl!([A, a], [B, b], [C, c], [D, d], [E, e], [F, f], [G, g]);
183into_params_impl!(
184 [A, a],
185 [B, b],
186 [C, c],
187 [D, d],
188 [E, e],
189 [F, f],
190 [G, g],
191 [H, h]
192);
193into_params_impl!(
194 [A, a],
195 [B, b],
196 [C, c],
197 [D, d],
198 [E, e],
199 [F, f],
200 [G, g],
201 [H, h],
202 [I, i]
203);
204into_params_impl!(
205 [A, a],
206 [B, b],
207 [C, c],
208 [D, d],
209 [E, e],
210 [F, f],
211 [G, g],
212 [H, h],
213 [I, i],
214 [J, j]
215);
216into_params_impl!(
217 [A, a],
218 [B, b],
219 [C, c],
220 [D, d],
221 [E, e],
222 [F, f],
223 [G, g],
224 [H, h],
225 [I, i],
226 [J, j],
227 [K, k]
228);
229into_params_impl!(
230 [A, a],
231 [B, b],
232 [C, c],
233 [D, d],
234 [E, e],
235 [F, f],
236 [G, g],
237 [H, h],
238 [I, i],
239 [J, j],
240 [K, k],
241 [L, l]
242);