c_main/
args.rs

1//! C style arguments wrapper
2
3#[derive(Copy, Clone, Debug)]
4///Wrapper over C-style arguments
5pub struct Args {
6    argc: usize,
7    argv: *const *const u8,
8}
9
10impl Args {
11    ///Creates new instance, but verifies that each string inside are UTF-8.
12    ///
13    ///On error returns pair: `(string index, Utf8Error)`
14    ///
15    ///The function is safe as long as you pass C style main function arguments.
16    pub unsafe fn new(argc: isize, argv: *const *const u8) -> Result<Self, (usize, core::str::Utf8Error)> {
17        assert!(argc > 0);
18        assert!(!argv.is_null());
19
20        let this = Args {
21            argc: argc as usize,
22            argv,
23        };
24
25        let args = this.as_slice();
26        for idx in 0..this.argc {
27            let arg = *args.get_unchecked(idx);
28            if let Err(error) = crate::c_str_to_rust(arg) {
29                return Err((idx, error));
30            }
31        }
32
33        Ok(this)
34    }
35
36    #[inline(always)]
37    ///Unchecked version of `Args::new`
38    ///
39    ///Do it on your own risk
40    pub unsafe fn new_unchecked(argc: isize, argv: *const *const u8) -> Self {
41        Args {
42            argc: argc as usize,
43            argv,
44        }
45    }
46
47    #[inline(always)]
48    ///Returns slice of raw C strings
49    pub fn as_slice(&self) -> &[*const u8] {
50        unsafe {
51            core::slice::from_raw_parts(self.argv, self.argc)
52        }
53    }
54
55    #[inline(always)]
56    ///Retrieves string by index.
57    ///
58    ///No checks, 100% unsafe.
59    pub unsafe fn get_str_by_index(&self, index: usize) -> &str {
60        let elem = *self.as_slice().get_unchecked(index);
61        crate::c_str_to_rust_unchecked(elem)
62    }
63}
64
65impl<'a> IntoIterator for &'a Args {
66    type Item = &'a str;
67    type IntoIter = IntoIter<'a>;
68
69    #[inline(always)]
70    fn into_iter(self) -> Self::IntoIter {
71        Self::IntoIter {
72            inner: self,
73            index: 0,
74        }
75    }
76}
77
78///Iterator over [Args](struct.Args.html)
79///
80///Comparing to normal iterators can be iterated back and forth.
81pub struct IntoIter<'a> {
82    inner: &'a Args,
83    index: usize,
84}
85
86impl<'a> Iterator for IntoIter<'a> {
87    type Item = &'a str;
88
89    fn next(&mut self) -> Option<Self::Item> {
90        if self.index >= self.inner.argc {
91            return None;
92        }
93
94        let elem = unsafe {
95            self.inner.get_str_by_index(self.index)
96        };
97        self.index += 1;
98        Some(elem)
99    }
100
101    #[inline(always)]
102    fn size_hint(&self) -> (usize, Option<usize>) {
103        let count = self.inner.argc - self.index;
104        (count, Some(count))
105    }
106
107    #[inline(always)]
108    fn count(self) -> usize {
109        self.inner.argc - self.index
110    }
111}
112