noodles_sam/io/indexed_reader/
builder.rs1use std::{
2 ffi::{OsStr, OsString},
3 fs::File,
4 io::{self, Read},
5 path::{Path, PathBuf},
6};
7
8use noodles_csi::{self as csi, BinningIndex};
9
10use super::IndexedReader;
11
12#[derive(Default)]
14pub struct Builder {
15 index: Option<Box<dyn BinningIndex>>,
16}
17
18impl Builder {
19 pub fn set_index<I>(mut self, index: I) -> Self
31 where
32 I: BinningIndex + 'static,
33 {
34 self.index = Some(Box::new(index));
35 self
36 }
37
38 pub fn build_from_path<P>(mut self, src: P) -> io::Result<IndexedReader<File>>
48 where
49 P: AsRef<Path>,
50 {
51 let src = src.as_ref();
52
53 if self.index.is_none() {
54 let index_src = build_index_src(src);
55 let index = csi::fs::read(index_src)?;
56 self.index = Some(Box::new(index));
57 }
58
59 let file = File::open(src)?;
60 self.build_from_reader(file)
61 }
62
63 pub fn build_from_reader<R>(self, reader: R) -> io::Result<IndexedReader<R>>
77 where
78 R: Read,
79 {
80 let index = self
81 .index
82 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "missing index"))?;
83
84 Ok(IndexedReader::new(reader, index))
85 }
86}
87
88fn build_index_src<P>(src: P) -> PathBuf
89where
90 P: AsRef<Path>,
91{
92 const EXT: &str = "csi";
93 push_ext(src.as_ref().into(), EXT)
94}
95
96fn push_ext<S>(path: PathBuf, ext: S) -> PathBuf
97where
98 S: AsRef<OsStr>,
99{
100 let mut s = OsString::from(path);
101 s.push(".");
102 s.push(ext);
103 PathBuf::from(s)
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_build_index_src() {
112 assert_eq!(
113 build_index_src("sample.sam.gz"),
114 PathBuf::from("sample.sam.gz.csi")
115 );
116 }
117}