1use crate::Opt;
4use core::cmp::Ordering;
5
6#[cfg(feature = "no_std")]
7use alloc::string::{String, ToString};
8
9pub const fn str_cmp(a: &str, b: &str) -> Ordering {
10 let (a, b) = (a.as_bytes(), b.as_bytes());
11 let mut i = 0;
12 let min_len = if a.len() < b.len() { a.len() } else { b.len() };
13
14 while i < min_len {
15 if a[i] != b[i] {
16 return if a[i] < b[i] {
17 Ordering::Less
18 } else {
19 Ordering::Greater
20 };
21 }
22 i += 1;
23 }
24
25 if a.len() < b.len() {
26 Ordering::Less
27 } else if a.len() > b.len() {
28 Ordering::Greater
29 } else {
30 Ordering::Equal
31 }
32}
33
34pub const fn opt_cmp(a: &Opt, b: &Opt) -> Ordering {
35 match str_cmp(a.lon, b.lon) {
36 Ordering::Less => Ordering::Less,
37 Ordering::Greater => Ordering::Greater,
38 Ordering::Equal => {
39 if a.sho < b.sho {
40 Ordering::Less
41 } else if a.sho > b.sho {
42 Ordering::Greater
43 } else {
44 if a.num < b.num {
45 Ordering::Less
46 } else if a.num > b.num {
47 Ordering::Greater
48 } else {
49 Ordering::Equal
50 }
51 }
52 }
53 }
54}
55
56pub const fn sort_opts<const N: usize>(mut opts: [Opt; N]) -> [Opt; N] {
57 let mut gap = N / 2;
58 while gap > 0 {
59 let mut i = gap;
60 while i < N {
61 let temp = opts[i];
62 let mut j = i;
63 while j >= gap {
64 match opt_cmp(&opts[j - gap], &temp) {
65 Ordering::Greater => {
66 opts[j] = opts[j - gap];
67 j -= gap;
68 }
69 _ => break,
70 }
71 }
72 opts[j] = temp;
73 i += 1;
74 }
75 gap /= 2;
76 }
77 opts
78}
79
80pub const fn count_short_opts<const N: usize>(opts: &[Opt; N]) -> usize {
81 let mut i = 0;
82 let mut count = 0;
83 while i < N {
84 if opts[i].sho != 0 {
85 count += 1;
86 }
87 i += 1;
88 }
89 count
90}
91
92pub const fn gen_sho_idx<const N: usize, const M: usize>(opts: &[Opt; N]) -> [(u8, usize); M] {
93 let mut res = [(0, 0); M];
94 let mut i = 0;
95 let mut count = 0;
96 while i < N {
97 if opts[i].sho != 0 {
98 res[count] = (opts[i].sho, i);
99 count += 1;
100 }
101 i += 1;
102 }
103 let mut gap = M / 2;
105 while gap > 0 {
106 let mut i = gap;
107 while i < M {
108 let temp = res[i];
109 let mut j = i;
110 while j >= gap {
111 if res[j - gap].0 > temp.0 {
112 res[j] = res[j - gap];
113 j -= gap;
114 } else {
115 break;
116 }
117 }
118 res[j] = temp;
119 i += 1;
120 }
121 gap /= 2;
122 }
123 res
124}
125
126pub trait ArgparseSet {
128 fn argparse_set(&mut self, val: Option<&str>, name: &str) -> Result<(), crate::OptParseError>;
129}
130
131impl ArgparseSet for bool {
132 fn argparse_set(&mut self, _val: Option<&str>, _name: &str) -> Result<(), crate::OptParseError> {
133 *self = true;
134 Ok(())
135 }
136}
137
138impl ArgparseSet for String {
139 fn argparse_set(&mut self, val: Option<&str>, _name: &str) -> Result<(), crate::OptParseError> {
140 if let Some(s) = val {
141 *self = s.to_string();
142 }
143 Ok(())
144 }
145}
146
147impl ArgparseSet for Option<String> {
148 fn argparse_set(&mut self, val: Option<&str>, _name: &str) -> Result<(), crate::OptParseError> {
149 if let Some(s) = val {
150 *self = Some(s.to_string());
151 } else {
152 *self = None;
153 }
154 Ok(())
155 }
156}
157
158macro_rules! impl_argparse_set_parse {
159 ($($t:ty),*) => {
160 $(
161 impl ArgparseSet for $t {
162 fn argparse_set(&mut self, val: Option<&str>, name: &str) -> Result<(), crate::OptParseError> {
163 if let Some(s) = val {
164 match s.parse::<$t>() {
165 Ok(v) => {
166 *self = v;
167 Ok(())
168 }
169 Err(_) => {
170 #[cfg(any(feature = "option_argument", feature = "dox"))]
171 return Err(crate::OptParseError::invalid_option_argument(name, s));
172 #[cfg(not(any(feature = "option_argument", feature = "dox")))]
173 return Err(crate::OptParseError::invalid_option(name));
174 }
175 }
176 } else {
177 Ok(())
178 }
179 }
180 }
181 )*
182 };
183}
184
185impl_argparse_set_parse!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64, usize, isize);