noshell/
lib.rs

1//! noshell, a `no_std` argument parser and a shell for constrained systems.
2#![no_std]
3#![deny(missing_docs)]
4
5pub use noshell_macros as macros;
6pub use noshell_parser as parser;
7
8pub use macros::Parser;
9
10/// Defines the possible errors that may occur during usage of the crate.
11#[derive(Debug, PartialEq, Eq, thiserror::Error)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13#[non_exhaustive]
14pub enum Error {
15    /// An error comes from the parsing of arguments.
16    #[error(transparent)]
17    Parser(#[from] parser::Error),
18}
19
20#[cfg(test)]
21mod tests {
22    use googletest::prelude::{assert_that, eq, matches_pattern};
23
24    use crate as noshell;
25
26    #[test]
27    fn it_should_parse_args_with_simple_type() {
28        #[derive(Debug, noshell::Parser)]
29        struct MyArgs {
30            value: u32,
31        }
32
33        let argv = &["--value", "233"];
34        let res = MyArgs::parse(argv);
35
36        assert_that!(res, matches_pattern!(Ok(_)));
37
38        let args = res.unwrap();
39        assert_that!(args.value, eq(233));
40    }
41
42    #[test]
43    fn it_should_parse_args_with_option_type() {
44        #[derive(Debug, noshell::Parser)]
45        struct MyArgs {
46            value: Option<u32>,
47        }
48
49        let argv = &[];
50        let res = MyArgs::parse(argv);
51
52        assert_that!(res.is_ok(), eq(true));
53
54        let args = res.unwrap();
55        assert_that!(args.value, eq(None));
56
57        let argv = &["--value", "233"];
58        let res = MyArgs::parse(argv);
59
60        assert_that!(res.is_ok(), eq(true));
61
62        let args = res.unwrap();
63        assert_that!(args.value, eq(Some(233)));
64    }
65
66    #[test]
67    fn it_should_parse_args_with_option_option_type() {
68        #[derive(Debug, noshell::Parser)]
69        struct MyArgs {
70            value: Option<Option<u32>>,
71        }
72
73        let argv = &[];
74        let res = MyArgs::parse(argv);
75
76        assert_that!(res.is_ok(), eq(true));
77
78        let args = res.unwrap();
79        assert_that!(args.value, eq(None));
80
81        let argv = &["--value"];
82        let res = MyArgs::parse(argv);
83
84        assert_that!(res.is_ok(), eq(true));
85
86        let args = res.unwrap();
87        assert_that!(args.value, eq(Some(None)));
88    }
89
90    #[test]
91    fn it_should_parse_args_with_option_vec_type() {
92        use heapless::Vec;
93
94        #[derive(Debug, noshell::Parser)]
95        struct MyArgs {
96            value: Option<Vec<u32, 8>>,
97        }
98
99        // No argument.
100        let argv = &[];
101        let res = MyArgs::parse(argv);
102
103        assert_that!(res.is_ok(), eq(true));
104
105        let args = res.unwrap();
106        assert_that!(args.value.is_none(), eq(true));
107
108        // Argument without value.
109        let argv = &["--value"];
110        let res = MyArgs::parse(argv);
111
112        assert_that!(res.is_ok(), eq(false));
113
114        // Argument with single value.
115        let argv = &["--value", "23"];
116        let res = MyArgs::parse(argv);
117
118        assert_that!(res.is_ok(), eq(true));
119        let args = res.unwrap();
120
121        assert_that!(args.value.is_some(), eq(true));
122        let vals = args.value.unwrap();
123
124        assert_that!(vals.is_empty(), eq(false));
125        assert_that!(vals.first().unwrap(), eq(&23));
126
127        // Argument with multiple values.
128        let argv = &["--value", "23", "42", "72"];
129        let res = MyArgs::parse(argv);
130
131        assert_that!(res.is_ok(), eq(true));
132        let args = res.unwrap();
133
134        assert_that!(args.value.is_some(), eq(true));
135        let vals = args.value.unwrap();
136
137        assert_that!(vals.is_empty(), eq(false));
138        let mut iter = vals.iter();
139
140        assert_that!(iter.next().unwrap(), eq(&23));
141        assert_that!(iter.next().unwrap(), eq(&42));
142        assert_that!(iter.next().unwrap(), eq(&72));
143        assert_that!(iter.next(), eq(None));
144    }
145
146    #[test]
147    #[should_panic]
148    fn it_should_panic_at_parsing_args_with_option_vec_type() {
149        use heapless::Vec;
150
151        #[derive(Debug, noshell::Parser)]
152        struct MyArgs {
153            #[allow(unused)]
154            value: Option<Vec<u32, 4>>,
155        }
156
157        // Argument with too much values.
158        let argv = &["--value", "1", "2", "3", "4", "5"];
159        let _ = MyArgs::parse(argv);
160    }
161
162    #[test]
163    fn it_should_parse_args_with_vec_type() {
164        use heapless::Vec;
165
166        #[derive(Debug, noshell::Parser)]
167        struct MyArgs {
168            value: Vec<u32, 8>,
169        }
170
171        // No argument.
172        let argv = &[];
173        let res = MyArgs::parse(argv);
174
175        assert_that!(res.is_ok(), eq(false));
176
177        // Argument without value.
178        let argv = &["--value"];
179        let res = MyArgs::parse(argv);
180
181        assert_that!(res.is_ok(), eq(false));
182
183        // Argument with single value.
184        let argv = &["--value", "23"];
185        let res = MyArgs::parse(argv);
186
187        assert_that!(res.is_ok(), eq(true));
188        let args = res.unwrap();
189
190        assert_that!(args.value.is_empty(), eq(false));
191        assert_that!(args.value.first().unwrap(), eq(&23));
192
193        // Argument with multiple values.
194        let argv = &["--value", "23", "42", "72"];
195        let res = MyArgs::parse(argv);
196
197        assert_that!(res.is_ok(), eq(true));
198        let args = res.unwrap();
199
200        assert_that!(args.value.is_empty(), eq(false));
201        let mut iter = args.value.iter();
202
203        assert_that!(iter.next().unwrap(), eq(&23));
204        assert_that!(iter.next().unwrap(), eq(&42));
205        assert_that!(iter.next().unwrap(), eq(&72));
206        assert_that!(iter.next(), eq(None));
207    }
208
209    #[test]
210    #[should_panic]
211    fn it_should_panic_at_parsing_args_with_vec_type() {
212        use heapless::Vec;
213
214        #[derive(Debug, noshell::Parser)]
215        struct MyArgs {
216            #[allow(unused)]
217            value: Vec<u32, 4>,
218        }
219
220        // Argument with too much values.
221        let argv = &["--value", "1", "2", "3", "4", "5"];
222        let _ = MyArgs::parse(argv);
223    }
224}