noodles_cram/io/writer/
builder.rs1use std::{
2 fs::File,
3 io::{self, Write},
4 path::Path,
5};
6
7use noodles_fasta as fasta;
8
9use super::{Options, Writer, RECORDS_PER_CONTAINER};
10use crate::{codecs::Encoder, container::BlockContentEncoderMap, file_definition::Version};
11
12#[derive(Default)]
14pub struct Builder {
15 reference_sequence_repository: fasta::Repository,
16 options: Options,
17}
18
19impl Builder {
20 pub fn set_reference_sequence_repository(
33 mut self,
34 reference_sequence_repository: fasta::Repository,
35 ) -> Self {
36 self.reference_sequence_repository = reference_sequence_repository;
37 self
38 }
39
40 pub fn preserve_read_names(mut self, value: bool) -> Self {
53 self.options.preserve_read_names = value;
54 self
55 }
56
57 pub fn encode_alignment_start_positions_as_deltas(mut self, value: bool) -> Self {
71 self.options.encode_alignment_start_positions_as_deltas = value;
72 self
73 }
74
75 pub fn set_block_content_encoder_map(mut self, map: BlockContentEncoderMap) -> Self {
87 self.options.block_content_encoder_map = map;
88 self
89 }
90
91 pub fn build_from_path<P>(self, dst: P) -> io::Result<Writer<File>>
101 where
102 P: AsRef<Path>,
103 {
104 File::create(dst).map(|file| self.build_from_writer(file))
105 }
106
107 #[deprecated(since = "0.68.0", note = "Use `Builder::build_from_path` instead.")]
109 pub fn build_with_path<P>(self, dst: P) -> io::Result<Writer<File>>
110 where
111 P: AsRef<Path>,
112 {
113 self.build_from_path(dst)
114 }
115
116 pub fn build_from_writer<W>(mut self, writer: W) -> Writer<W>
125 where
126 W: Write,
127 {
128 if uses_cram_3_1_codecs(&self.options.block_content_encoder_map) {
129 self.options.version = Version::new(3, 1);
130 }
131
132 Writer {
133 inner: writer,
134 reference_sequence_repository: self.reference_sequence_repository,
135 options: self.options,
136 records: Vec::with_capacity(RECORDS_PER_CONTAINER),
137 record_counter: 0,
138 }
139 }
140
141 #[deprecated(since = "0.68.0", note = "Use `Builder::build_from_writer` instead.")]
143 pub fn build_with_writer<W>(self, writer: W) -> Writer<W>
144 where
145 W: Write,
146 {
147 self.build_from_writer(writer)
148 }
149}
150
151pub fn uses_cram_3_1_codecs(block_content_encoder_map: &BlockContentEncoderMap) -> bool {
152 fn is_cram_3_1_codec(encoder: &Encoder) -> bool {
153 matches!(
154 encoder,
155 Encoder::RansNx16(_) | Encoder::AdaptiveArithmeticCoding(_) | Encoder::NameTokenizer
156 )
157 }
158
159 if let Some(encoder) = block_content_encoder_map.core_data_encoder() {
160 if is_cram_3_1_codec(encoder) {
161 return true;
162 }
163 }
164
165 block_content_encoder_map
166 .data_series_encoders()
167 .iter()
168 .chain(block_content_encoder_map.tag_values_encoders().values())
169 .flatten()
170 .any(is_cram_3_1_codec)
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_uses_cram_3_1_codecs() {
179 use crate::codecs::rans_nx16::Flags;
180
181 let block_content_encoder_map = BlockContentEncoderMap::default();
182 assert!(!uses_cram_3_1_codecs(&block_content_encoder_map));
183
184 let block_content_encoder_map = BlockContentEncoderMap::builder()
185 .set_core_data_encoder(Some(Encoder::RansNx16(Flags::empty())))
186 .build();
187 assert!(uses_cram_3_1_codecs(&block_content_encoder_map));
188 }
189}