noodles_bcf/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_bgzf as bgzf;
9use noodles_csi::{self as csi, BinningIndex};
10
11use super::IndexedReader;
12
13#[derive(Default)]
15pub struct Builder {
16 index: Option<Box<dyn BinningIndex>>,
17}
18
19impl Builder {
20 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>(self, src: P) -> io::Result<IndexedReader<bgzf::Reader<File>>>
48 where
49 P: AsRef<Path>,
50 {
51 let src = src.as_ref();
52
53 let file = File::open(src)?;
54
55 let index = match self.index {
56 Some(index) => index,
57 None => read_associated_index(src)?,
58 };
59
60 Ok(IndexedReader::new(file, index))
61 }
62
63 pub fn build_from_reader<R>(self, reader: R) -> io::Result<IndexedReader<bgzf::Reader<R>>>
76 where
77 R: Read,
78 {
79 let index = self
80 .index
81 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "missing index"))?;
82
83 Ok(IndexedReader::new(reader, index))
84 }
85}
86
87fn read_associated_index<P>(src: P) -> io::Result<Box<dyn BinningIndex>>
88where
89 P: AsRef<Path>,
90{
91 let index = csi::fs::read(build_index_src(src))?;
92 Ok(Box::new(index))
93}
94
95fn build_index_src<P>(src: P) -> PathBuf
96where
97 P: AsRef<Path>,
98{
99 const EXT: &str = "csi";
100 push_ext(src.as_ref().into(), EXT)
101}
102
103fn push_ext<S>(path: PathBuf, ext: S) -> PathBuf
104where
105 S: AsRef<OsStr>,
106{
107 let mut s = OsString::from(path);
108 s.push(".");
109 s.push(ext);
110 PathBuf::from(s)
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_build_index_src() {
119 assert_eq!(
120 build_index_src("sample.bcf"),
121 PathBuf::from("sample.bcf.csi")
122 );
123 }
124}