1
use color_eyre::{eyre::eyre, Result};
2
use std::ffi::OsStr;
3
use std::path::{Path, PathBuf};
4

            
5
use crate::io::read_lines;
6

            
7
#[doc(hidden)]
8
13
fn return_double_extension_filetype(path: &Path, e1: &str) -> Result<String> {
9
13
    let stem = path
10
13
        .file_stem()
11
13
        .and_then(OsStr::to_str)
12
13
        .ok_or_else(|| eyre::eyre!("file has no stem"))?;
13
13
    let e2 = Path::new(&stem)
14
13
        .extension()
15
13
        .and_then(OsStr::to_str)
16
13
        .ok_or_else(|| eyre::eyre!("file has no other filetype"))?;
17
13
    Ok(format!("{e2}.{e1}"))
18
13
}
19

            
20
24
pub fn get_sample_names(path: PathBuf) -> Result<Vec<String>> {
21
24
    let extension: &str = Path::new(&path)
22
24
        .extension()
23
24
        .and_then(OsStr::to_str)
24
24
        .ok_or_else(|| eyre!("No filetype in path"))?;
25

            
26
24
    let extension = match extension {
27
24
        "gz" | "bgz" => return_double_extension_filetype(&path, extension)?,
28
12
        _ => extension.to_string(),
29
    };
30

            
31
24
    let mut ids = vec![];
32
24
    match extension.as_str() {
33
24
        "vcf.gz" | "vcf" | "bcf" => {
34
            use rust_htslib::bcf::{Read, Reader};
35
12
            let bcf = Reader::from_path(path).expect("Error opening file.");
36
12
            let header = bcf.header().clone();
37
12
            let samples = header.samples();
38
180
            for sample in samples {
39
168
                let id = std::str::from_utf8(sample)?;
40
168
                ids.push(id.to_string());
41
            }
42
        }
43
12
        "fam" => {
44
48
            for line in read_lines(path)?.flatten() {
45
48
                let mut split = line.split('\t');
46
48
                let id = split
47
48
                    .nth(1)
48
48
                    .expect("error splitting by column, is the file tab delimited?");
49
48
                ids.push(id.to_string());
50
48
            }
51
        }
52
        _ => return Err(eyre!("filetype not supported for: {}", extension)),
53
    }
54
24
    Ok(ids)
55
24
}
56

            
57
#[doc(hidden)]
58
12
pub fn run(path: PathBuf) -> Result<()> {
59
12
    let ids = get_sample_names(path)?;
60
120
    for id in ids {
61
108
        println!("{id}");
62
108
    }
63
12
    Ok(())
64
12
}
65

            
66
#[cfg(test)]
67
#[rustfmt::skip]
68
mod tests {
69
    use super::*;
70

            
71
1
    #[test]
72
1
    fn test_extension_filetype() {
73
1
        let path = std::path::PathBuf::from("test.vcf.gz");
74
1
        let ftype = return_double_extension_filetype(&path, "gz").unwrap();
75
1
        assert_eq!(String::from("vcf.gz"), ftype);
76
1
    }
77
}