postgres_named_parameters_derive/
numberify.rs

1pub fn numberify(query: String, parameters: Vec<String>) -> Result<String, String> {
2    let mut input = query.chars().peekable();
3    let mut output = String::new();
4
5    loop {
6        match input.next() {
7            None => return Ok(output),
8            Some('@') => {
9                match input.peek() {
10                    None => return Err("Input SQL should not end with '@'. If a single literal '@' is desired, it should be doubled ('@@')".to_owned()),
11                    Some('@') => {
12                        // escaped '@' (i.e. '@@' -> '@')
13                        output.push(input.next().unwrap())
14                    },
15                    Some(_) => {
16                        let mut field_name = String::new();
17
18                        while let Some(ch) = input.peek() {
19                            if ch.is_alphanumeric() || *ch == '_' {
20                                field_name.push(input.next().unwrap());
21                            } else {
22                                break;
23                            }
24                        }
25
26                        match parameters.iter().position(|field| field_name == *field) {
27                            Some(raw_index) => {
28                                let sql_index = raw_index + 1;
29                                output.push_str(&format!("${}", sql_index));
30                            },
31                            None => return Err(format!(
32                                r#"The provided SQL contains "@{}", but there is no matching field in the struct with the name "{}""#,
33                                field_name,
34                                field_name,
35                            ))
36                        }
37                    }
38                }
39            },
40
41            // regular characters not in a field name pass through to the output
42            Some(ch) => output.push(ch)
43        }
44    }
45}