noodles_cram/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_fasta as fasta;
9
10use super::IndexedReader;
11use crate::crai;
12
13#[derive(Default)]
15pub struct Builder {
16 reference_sequence_repository: fasta::Repository,
17 index: Option<crai::Index>,
18}
19
20impl Builder {
21 pub fn set_reference_sequence_repository(
34 mut self,
35 reference_sequence_repository: fasta::Repository,
36 ) -> Self {
37 self.reference_sequence_repository = reference_sequence_repository;
38 self
39 }
40
41 pub fn set_index(mut self, index: crai::Index) -> Self {
51 self.index = Some(index);
52 self
53 }
54
55 pub fn build_from_path<P>(mut self, src: P) -> io::Result<IndexedReader<File>>
67 where
68 P: AsRef<Path>,
69 {
70 let src = src.as_ref();
71
72 if self.index.is_none() {
73 let index_src = build_index_src(src);
74 self.index = crai::fs::read(index_src).map(Some)?;
75 }
76
77 let file = File::open(src)?;
78 self.build_from_reader(file)
79 }
80
81 pub fn build_from_reader<R>(self, reader: R) -> io::Result<IndexedReader<R>>
96 where
97 R: Read,
98 {
99 let inner = crate::io::reader::Builder::default()
100 .set_reference_sequence_repository(self.reference_sequence_repository)
101 .build_from_reader(reader);
102
103 let index = self
104 .index
105 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "missing index"))?;
106
107 Ok(IndexedReader { inner, index })
108 }
109}
110
111fn build_index_src<P>(src: P) -> PathBuf
112where
113 P: AsRef<Path>,
114{
115 const EXT: &str = "crai";
116 push_ext(src.as_ref().into(), EXT)
117}
118
119fn push_ext<S>(path: PathBuf, ext: S) -> PathBuf
120where
121 S: AsRef<OsStr>,
122{
123 let mut s = OsString::from(path);
124 s.push(".");
125 s.push(ext);
126 PathBuf::from(s)
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_build_index_src() {
135 assert_eq!(
136 build_index_src("sample.cram"),
137 PathBuf::from("sample.cram.crai")
138 );
139 }
140}