//! Null-separated path-list parsing helpers.

use std::{ffi::OsStr, os::unix::ffi::OsStrExt, path::Path};

/// Parses a NUL-separated path list into borrowed paths.
///
/// Empty segments are ignored. Returned paths borrow from `bytes`.
pub fn paths_from_null_separated_bytes(bytes: &[u8]) -> Vec<&Path> {
    bytes
        .split(|byte| *byte == 0)
        .filter(|segment| !segment.is_empty())
        .map(|segment| Path::new(OsStr::from_bytes(segment)))
        .collect()
}

#[cfg(test)]
mod tests {
    use std::path::Path;

    use super::paths_from_null_separated_bytes;

    #[test]
    fn paths_from_null_separated_bytes_returns_empty_list_for_empty_input() {
        let paths = paths_from_null_separated_bytes(b"");

        assert!(paths.is_empty());
    }

    #[test]
    fn paths_from_null_separated_bytes_ignores_empty_segments() {
        let paths = paths_from_null_separated_bytes(b"\0a.rs\0\0b.rs\0");

        assert_eq!(paths, vec![Path::new("a.rs"), Path::new("b.rs")]);
    }

    #[test]
    fn paths_from_null_separated_bytes_accepts_final_path_without_trailing_nul() {
        let paths = paths_from_null_separated_bytes(b"a.rs\0b.rs");

        assert_eq!(paths, vec![Path::new("a.rs"), Path::new("b.rs")]);
    }

    #[test]
    fn paths_from_null_separated_bytes_preserves_order() {
        let paths = paths_from_null_separated_bytes(b"b.rs\0a.rs\0c.rs\0");

        assert_eq!(
            paths,
            vec![Path::new("b.rs"), Path::new("a.rs"), Path::new("c.rs")]
        );
    }
}
