Skip to main content

relibc/header/unistd/
path.rs

1use core::slice::Split;
2
3use arrayvec::ArrayVec;
4
5use crate::{c_str::CStr, header::limits::PATH_MAX};
6
7pub struct PathSearchIter<'a> {
8    file_bytes: &'a [u8],
9    path_splits: Split<'a, u8, fn(&u8) -> bool>,
10}
11
12const PATH_SEPARATOR: u8 = b':';
13
14impl<'a> PathSearchIter<'a> {
15    /// Construct a new PATH parser.
16    /// Safety: file must have no slashes
17    pub fn new(file_bytes: &'a [u8], path_env: &'a CStr) -> Self {
18        Self {
19            file_bytes,
20            path_splits: path_env.to_bytes().split(|&b| b == PATH_SEPARATOR),
21        }
22    }
23}
24
25impl<'a> Iterator for PathSearchIter<'a> {
26    type Item = ArrayVec<u8, PATH_MAX>;
27
28    fn next(&mut self) -> Option<Self::Item> {
29        for path in &mut self.path_splits {
30            let len = path.len() + self.file_bytes.len() + 2;
31            if len > PATH_MAX {
32                continue;
33            }
34            let mut program: ArrayVec<u8, PATH_MAX> = ArrayVec::new();
35            program.try_extend_from_slice(path).unwrap();
36            program.push(b'/');
37            program.try_extend_from_slice(self.file_bytes).unwrap();
38            program.push(b'\0');
39            return Some(program);
40        }
41
42        None
43    }
44}