1use crate::{Result, parse};
2
3pub fn extract_params(input: &str) -> Result<Vec<String>> {
20 parse(input)?;
21 Ok(scan_params(input))
22}
23
24pub(crate) fn scan_params(input: &str) -> Vec<String> {
28 let mut params = std::collections::BTreeSet::new();
29 let bytes = input.as_bytes();
30 let len = bytes.len();
31 let mut i = 0;
32
33 while i < len {
34 match bytes[i] {
35 b'\'' => {
37 i += 1;
38 while i < len {
39 if bytes[i] == b'\'' {
40 i += 1;
41 if i < len && bytes[i] == b'\'' {
42 i += 1; continue;
44 }
45 break;
46 }
47 i += 1;
48 }
49 }
50 b'"' => {
52 i += 1;
53 while i < len {
54 if bytes[i] == b'\\' {
55 i += 2;
56 continue;
57 }
58 if bytes[i] == b'"' {
59 i += 1;
60 break;
61 }
62 i += 1;
63 }
64 }
65 b'`' => {
67 i += 1;
68 while i < len {
69 if bytes[i] == b'`' {
70 i += 1;
71 break;
72 }
73 i += 1;
74 }
75 }
76 b'-' if i + 1 < len && bytes[i + 1] == b'-' => {
78 i += 2;
79 while i < len && bytes[i] != b'\n' {
80 i += 1;
81 }
82 }
83 b'/' if i + 1 < len && bytes[i + 1] == b'*' => {
85 i += 2;
86 let mut depth = 1u32;
87 while i + 1 < len && depth > 0 {
88 if bytes[i] == b'/' && bytes[i + 1] == b'*' {
89 depth += 1;
90 i += 2;
91 } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
92 depth -= 1;
93 i += 2;
94 } else {
95 i += 1;
96 }
97 }
98 }
99 b'$' => {
101 i += 1;
102 let start = i;
103 while i < len && (bytes[i].is_ascii_alphanumeric() || bytes[i] == b'_') {
104 i += 1;
105 }
106 if i > start {
107 let name = &input[start..i];
108 params.insert(name.to_string());
109 }
110 }
111 _ => i += 1,
112 }
113 }
114
115 params.into_iter().collect()
116}