1use std::{io::Read, marker::PhantomData};
4
5use crate::{
6 block::{
7 BlockDecoder,
8 name::{NameCodec, OmittedNameCodec, RawNameCodec},
9 quality::{OmittedQualityCodec, QualityCodec, RawQualityCodec},
10 sequence::{OmittedSequenceCodec, RawAsciiCodec, SequenceCodec, TwoBitExactCodec},
11 },
12 error::DryIceError,
13 fields::{AllFields, HasKey, HasName, HasQuality, HasSequence, SelectionExpr, SelectionPlan},
14 format,
15 key::{Bytes8Key, Bytes16Key, NoRecordKey, RecordKey},
16 record::{SeqRecord, SeqRecordExt, SeqRecordLike},
17};
18
19#[doc(hidden)]
21pub struct MissingInner;
22
23#[doc(hidden)]
25pub struct ReadAllFields;
26
27#[doc(hidden)]
29pub struct ReadSelectedFields<F>(PhantomData<F>);
30
31pub struct SelectedDryIceReader<
37 R,
38 S = RawAsciiCodec,
39 Q = RawQualityCodec,
40 N = RawNameCodec,
41 K = NoRecordKey,
42 F = ReadAllFields,
43> {
44 inner: DryIceReader<R, S, Q, N, K>,
45 _fields: PhantomData<F>,
46}
47
48pub struct SelectedRecord<
54 'a,
55 R,
56 S = RawAsciiCodec,
57 Q = RawQualityCodec,
58 N = RawNameCodec,
59 K = NoRecordKey,
60 F = ReadAllFields,
61> {
62 reader: &'a DryIceReader<R, S, Q, N, K>,
63 _fields: PhantomData<F>,
64}
65
66pub type SelectedRecordView<'a, R, S, Q, N, K, F> = SelectedRecord<'a, R, S, Q, N, K, F>;
69
70pub type SelectedNextRecord<'a, R, S, Q, N, K, F> =
72 Option<SelectedRecordView<'a, R, S, Q, N, K, F>>;
73
74fn verify_block_codecs<S, Q, N>(
75 header: &crate::block::header::BlockHeader,
76) -> Result<(), DryIceError>
77where
78 S: SequenceCodec,
79 Q: QualityCodec,
80 N: NameCodec,
81{
82 if header.sequence_codec_tag != S::TYPE_TAG {
83 return Err(DryIceError::SequenceCodecMismatch {
84 expected: S::TYPE_TAG,
85 found: header.sequence_codec_tag,
86 });
87 }
88 if header.quality_codec_tag != Q::TYPE_TAG {
89 return Err(DryIceError::QualityCodecMismatch {
90 expected: Q::TYPE_TAG,
91 found: header.quality_codec_tag,
92 });
93 }
94 if header.name_codec_tag != N::TYPE_TAG {
95 return Err(DryIceError::NameCodecMismatch {
96 expected: N::TYPE_TAG,
97 found: header.name_codec_tag,
98 });
99 }
100 Ok(())
101}
102
103pub struct DryIceReaderBuilder<
105 R = MissingInner,
106 S = RawAsciiCodec,
107 Q = RawQualityCodec,
108 N = RawNameCodec,
109 K = NoRecordKey,
110 M = ReadAllFields,
111> {
112 inner: R,
113 _codec: PhantomData<S>,
114 _quality: PhantomData<Q>,
115 _name: PhantomData<N>,
116 _key: PhantomData<K>,
117 _mode: PhantomData<M>,
118}
119
120impl
121 DryIceReaderBuilder<
122 MissingInner,
123 RawAsciiCodec,
124 RawQualityCodec,
125 RawNameCodec,
126 NoRecordKey,
127 ReadAllFields,
128 >
129{
130 fn new() -> Self {
131 Self {
132 inner: MissingInner,
133 _codec: PhantomData,
134 _quality: PhantomData,
135 _name: PhantomData,
136 _key: PhantomData,
137 _mode: PhantomData,
138 }
139 }
140}
141
142impl<S, Q, N, K, M> DryIceReaderBuilder<MissingInner, S, Q, N, K, M> {
143 #[must_use]
145 pub fn inner<R>(self, inner: R) -> DryIceReaderBuilder<R, S, Q, N, K, M> {
146 DryIceReaderBuilder {
147 inner,
148 _codec: self._codec,
149 _quality: self._quality,
150 _name: self._name,
151 _key: self._key,
152 _mode: self._mode,
153 }
154 }
155}
156
157impl<R, Q, N, K, M> DryIceReaderBuilder<R, RawAsciiCodec, Q, N, K, M> {
158 #[must_use]
160 pub fn sequence_codec<S: SequenceCodec>(self) -> DryIceReaderBuilder<R, S, Q, N, K, M> {
161 DryIceReaderBuilder {
162 inner: self.inner,
163 _codec: PhantomData,
164 _quality: PhantomData,
165 _name: PhantomData,
166 _key: PhantomData,
167 _mode: PhantomData,
168 }
169 }
170
171 #[must_use]
173 pub fn two_bit_exact(self) -> DryIceReaderBuilder<R, TwoBitExactCodec, Q, N, K, M> {
174 self.sequence_codec::<TwoBitExactCodec>()
175 }
176
177 #[must_use]
179 pub fn omit_sequence(self) -> DryIceReaderBuilder<R, OmittedSequenceCodec, Q, N, K, M> {
180 self.sequence_codec::<OmittedSequenceCodec>()
181 }
182}
183
184impl<R, S, N, K, M> DryIceReaderBuilder<R, S, RawQualityCodec, N, K, M> {
185 #[must_use]
187 pub fn quality_codec<Q: QualityCodec>(self) -> DryIceReaderBuilder<R, S, Q, N, K, M> {
188 DryIceReaderBuilder {
189 inner: self.inner,
190 _codec: PhantomData,
191 _quality: PhantomData,
192 _name: PhantomData,
193 _key: PhantomData,
194 _mode: PhantomData,
195 }
196 }
197
198 #[must_use]
200 pub fn omit_quality(self) -> DryIceReaderBuilder<R, S, OmittedQualityCodec, N, K, M> {
201 self.quality_codec::<OmittedQualityCodec>()
202 }
203}
204
205impl<R, S, Q, K, M> DryIceReaderBuilder<R, S, Q, RawNameCodec, K, M> {
206 #[must_use]
208 pub fn name_codec<N: NameCodec>(self) -> DryIceReaderBuilder<R, S, Q, N, K, M> {
209 DryIceReaderBuilder {
210 inner: self.inner,
211 _codec: PhantomData,
212 _quality: PhantomData,
213 _name: PhantomData,
214 _key: PhantomData,
215 _mode: PhantomData,
216 }
217 }
218
219 #[must_use]
221 pub fn omit_names(self) -> DryIceReaderBuilder<R, S, Q, OmittedNameCodec, K, M> {
222 self.name_codec::<OmittedNameCodec>()
223 }
224}
225
226impl<R, S, Q, N, M> DryIceReaderBuilder<R, S, Q, N, NoRecordKey, M> {
227 #[must_use]
229 pub fn record_key<K: RecordKey>(self) -> DryIceReaderBuilder<R, S, Q, N, K, M> {
230 DryIceReaderBuilder {
231 inner: self.inner,
232 _codec: PhantomData,
233 _quality: PhantomData,
234 _name: PhantomData,
235 _key: PhantomData,
236 _mode: PhantomData,
237 }
238 }
239
240 #[must_use]
242 pub fn bytes8_key(self) -> DryIceReaderBuilder<R, S, Q, N, Bytes8Key, M> {
243 self.record_key::<Bytes8Key>()
244 }
245
246 #[must_use]
248 pub fn bytes16_key(self) -> DryIceReaderBuilder<R, S, Q, N, Bytes16Key, M> {
249 self.record_key::<Bytes16Key>()
250 }
251}
252
253impl<R, S, Q, N, K> DryIceReaderBuilder<R, S, Q, N, K, ReadAllFields> {
254 #[must_use]
262 pub fn select<F: SelectionExpr>(
263 self,
264 _fields: F,
265 ) -> DryIceReaderBuilder<R, S, Q, N, K, ReadSelectedFields<F>> {
266 DryIceReaderBuilder {
267 inner: self.inner,
268 _codec: PhantomData,
269 _quality: PhantomData,
270 _name: PhantomData,
271 _key: PhantomData,
272 _mode: PhantomData,
273 }
274 }
275}
276
277impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec>
278 DryIceReaderBuilder<R, S, Q, N, NoRecordKey, ReadAllFields>
279{
280 pub fn build(mut self) -> Result<DryIceReader<R, S, Q, N, NoRecordKey>, DryIceError> {
282 format::read_file_header(&mut self.inner)?;
283 Ok(DryIceReader {
284 inner: self.inner,
285 current_block: None,
286 _codec: PhantomData,
287 _quality: PhantomData,
288 _name: PhantomData,
289 _key: PhantomData,
290 })
291 }
292}
293
294impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K: RecordKey>
295 DryIceReaderBuilder<R, S, Q, N, K, ReadAllFields>
296{
297 pub fn build(mut self) -> Result<DryIceReader<R, S, Q, N, K>, DryIceError> {
299 format::read_file_header(&mut self.inner)?;
300 Ok(DryIceReader {
301 inner: self.inner,
302 current_block: None,
303 _codec: PhantomData,
304 _quality: PhantomData,
305 _name: PhantomData,
306 _key: PhantomData,
307 })
308 }
309}
310
311impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, F: SelectionPlan>
312 DryIceReaderBuilder<R, S, Q, N, NoRecordKey, ReadSelectedFields<F>>
313{
314 pub fn build(
316 mut self,
317 ) -> Result<SelectedDryIceReader<R, S, Q, N, NoRecordKey, F>, DryIceError> {
318 format::read_file_header(&mut self.inner)?;
319 Ok(SelectedDryIceReader {
320 inner: DryIceReader {
321 inner: self.inner,
322 current_block: None,
323 _codec: PhantomData,
324 _quality: PhantomData,
325 _name: PhantomData,
326 _key: PhantomData,
327 },
328 _fields: PhantomData,
329 })
330 }
331}
332
333impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K: RecordKey, F: SelectionPlan>
334 DryIceReaderBuilder<R, S, Q, N, K, ReadSelectedFields<F>>
335{
336 pub fn build(mut self) -> Result<SelectedDryIceReader<R, S, Q, N, K, F>, DryIceError> {
338 format::read_file_header(&mut self.inner)?;
339 Ok(SelectedDryIceReader {
340 inner: DryIceReader {
341 inner: self.inner,
342 current_block: None,
343 _codec: PhantomData,
344 _quality: PhantomData,
345 _name: PhantomData,
346 _key: PhantomData,
347 },
348 _fields: PhantomData,
349 })
350 }
351}
352
353pub struct DryIceReader<
355 R,
356 S = RawAsciiCodec,
357 Q = RawQualityCodec,
358 N = RawNameCodec,
359 K = NoRecordKey,
360> {
361 inner: R,
362 current_block: Option<BlockDecoder>,
363 _codec: PhantomData<S>,
364 _quality: PhantomData<Q>,
365 _name: PhantomData<N>,
366 _key: PhantomData<K>,
367}
368
369impl DryIceReader<MissingInner, RawAsciiCodec, RawQualityCodec, RawNameCodec, NoRecordKey> {
370 #[must_use]
372 pub fn builder() -> DryIceReaderBuilder<
373 MissingInner,
374 RawAsciiCodec,
375 RawQualityCodec,
376 RawNameCodec,
377 NoRecordKey,
378 ReadAllFields,
379 > {
380 DryIceReaderBuilder::new()
381 }
382}
383
384impl<R: Read> DryIceReader<R, RawAsciiCodec, RawQualityCodec, RawNameCodec, NoRecordKey> {
385 pub fn new(mut inner: R) -> Result<Self, DryIceError> {
392 format::read_file_header(&mut inner)?;
393 Ok(Self {
394 inner,
395 current_block: None,
396 _codec: PhantomData,
397 _quality: PhantomData,
398 _name: PhantomData,
399 _key: PhantomData,
400 })
401 }
402
403 pub fn with_two_bit_exact(
410 mut inner: R,
411 ) -> Result<
412 DryIceReader<R, TwoBitExactCodec, RawQualityCodec, RawNameCodec, NoRecordKey>,
413 DryIceError,
414 > {
415 format::read_file_header(&mut inner)?;
416 Ok(DryIceReader {
417 inner,
418 current_block: None,
419 _codec: PhantomData,
420 _quality: PhantomData,
421 _name: PhantomData,
422 _key: PhantomData,
423 })
424 }
425
426 pub fn with_codecs<S: SequenceCodec, Q: QualityCodec, N: NameCodec>(
433 mut inner: R,
434 ) -> Result<DryIceReader<R, S, Q, N, NoRecordKey>, DryIceError> {
435 format::read_file_header(&mut inner)?;
436 Ok(DryIceReader {
437 inner,
438 current_block: None,
439 _codec: PhantomData,
440 _quality: PhantomData,
441 _name: PhantomData,
442 _key: PhantomData,
443 })
444 }
445
446 pub fn with_record_key<K2: RecordKey>(
454 mut inner: R,
455 ) -> Result<DryIceReader<R, RawAsciiCodec, RawQualityCodec, RawNameCodec, K2>, DryIceError>
456 {
457 format::read_file_header(&mut inner)?;
458 Ok(DryIceReader {
459 inner,
460 current_block: None,
461 _codec: PhantomData,
462 _quality: PhantomData,
463 _name: PhantomData,
464 _key: PhantomData,
465 })
466 }
467
468 pub fn with_bytes8_key(
475 inner: R,
476 ) -> Result<DryIceReader<R, RawAsciiCodec, RawQualityCodec, RawNameCodec, Bytes8Key>, DryIceError>
477 {
478 Self::with_record_key::<Bytes8Key>(inner)
479 }
480
481 pub fn with_bytes16_key(
488 inner: R,
489 ) -> Result<
490 DryIceReader<R, RawAsciiCodec, RawQualityCodec, RawNameCodec, Bytes16Key>,
491 DryIceError,
492 > {
493 Self::with_record_key::<Bytes16Key>(inner)
494 }
495}
496
497impl<R: Read> DryIceReader<R> {
498 pub fn open<S: SequenceCodec, Q: QualityCodec, N: NameCodec, K: RecordKey>(
512 mut inner: R,
513 ) -> Result<DryIceReader<R, S, Q, N, K>, DryIceError> {
514 format::read_file_header(&mut inner)?;
515 Ok(DryIceReader {
516 inner,
517 current_block: None,
518 _codec: PhantomData,
519 _quality: PhantomData,
520 _name: PhantomData,
521 _key: PhantomData,
522 })
523 }
524}
525
526impl<R, S, Q, N, K, F> SelectedDryIceReader<R, S, Q, N, K, F>
527where
528 R: Read,
529 S: SequenceCodec,
530 Q: QualityCodec,
531 N: NameCodec,
532 F: SelectionPlan,
533{
534 pub fn next_record(&mut self) -> Result<SelectedNextRecord<'_, R, S, Q, N, K, F>, DryIceError> {
542 if self.inner.next_record_prepared::<F>()? {
543 Ok(Some(SelectedRecord {
544 reader: &self.inner,
545 _fields: PhantomData,
546 }))
547 } else {
548 Ok(None)
549 }
550 }
551}
552
553impl<R, S, Q, N, K, F> SelectedRecord<'_, R, S, Q, N, K, F>
554where
555 R: Read,
556 S: SequenceCodec,
557 Q: QualityCodec,
558 N: NameCodec,
559 F: SelectionExpr + HasName,
560{
561 #[must_use]
563 pub fn name(&self) -> &[u8] {
564 self.reader.name()
565 }
566}
567
568impl<R, S, Q, N, K, F> SelectedRecord<'_, R, S, Q, N, K, F>
569where
570 R: Read,
571 S: SequenceCodec,
572 Q: QualityCodec,
573 N: NameCodec,
574 F: SelectionExpr + HasSequence,
575{
576 #[must_use]
578 pub fn sequence(&self) -> &[u8] {
579 self.reader.sequence()
580 }
581}
582
583impl<R, S, Q, N, K, F> SelectedRecord<'_, R, S, Q, N, K, F>
584where
585 R: Read,
586 S: SequenceCodec,
587 Q: QualityCodec,
588 N: NameCodec,
589 F: SelectionExpr + HasQuality,
590{
591 #[must_use]
593 pub fn quality(&self) -> &[u8] {
594 self.reader.quality()
595 }
596}
597
598impl<R, S, Q, N, K, F> SelectedRecord<'_, R, S, Q, N, K, F>
599where
600 R: Read,
601 S: SequenceCodec,
602 Q: QualityCodec,
603 N: NameCodec,
604 K: RecordKey,
605 F: SelectionExpr + HasKey,
606{
607 pub fn record_key(&self) -> Result<K, DryIceError> {
614 self.reader.record_key()
615 }
616}
617
618impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K: RecordKey>
619 DryIceReader<R, S, Q, N, K>
620{
621 pub fn record_key(&self) -> Result<K, DryIceError> {
629 let block = self
630 .current_block
631 .as_ref()
632 .ok_or(DryIceError::MissingRecordKeySection)?;
633 block.verify_record_key::<K>()?;
634 K::decode_from(block.current_record_key_bytes()?)
635 }
636
637 pub fn next_key(&mut self) -> Result<Option<K>, DryIceError> {
644 if self.next_record()? {
645 Ok(Some(self.record_key()?))
646 } else {
647 Ok(None)
648 }
649 }
650}
651
652impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K> DryIceReader<R, S, Q, N, K> {
653 fn next_record_prepared<P>(&mut self) -> Result<bool, DryIceError>
654 where
655 P: SelectionPlan,
656 {
657 if let Some(block) = &mut self.current_block
658 && block.advance::<S, Q, N, P>()?
659 {
660 return Ok(true);
661 }
662
663 loop {
664 if let Some(header) = format::read_block_header(&mut self.inner)? {
665 verify_block_codecs::<S, Q, N>(&header)?;
666 let mut decoder = BlockDecoder::from_header_and_reader(header, &mut self.inner)?;
667 if decoder.advance::<S, Q, N, P>()? {
668 self.current_block = Some(decoder);
669 return Ok(true);
670 }
671 } else {
672 self.current_block = None;
673 return Ok(false);
674 }
675 }
676 }
677
678 pub fn next_record(&mut self) -> Result<bool, DryIceError> {
686 self.next_record_prepared::<AllFields>()
687 }
688
689 pub fn into_records(self) -> DryIceRecords<R, S, Q, N, K> {
691 DryIceRecords { reader: self }
692 }
693}
694
695impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K> SeqRecordLike
696 for DryIceReader<R, S, Q, N, K>
697{
698 fn name(&self) -> &[u8] {
699 self.current_block
700 .as_ref()
701 .expect("name() called with no current record")
702 .current_name()
703 }
704
705 fn sequence(&self) -> &[u8] {
706 self.current_block
707 .as_ref()
708 .expect("sequence() called with no current record")
709 .current_sequence()
710 }
711
712 fn quality(&self) -> &[u8] {
713 self.current_block
714 .as_ref()
715 .expect("quality() called with no current record")
716 .current_quality()
717 }
718}
719
720pub struct DryIceRecords<
722 R,
723 S = RawAsciiCodec,
724 Q = RawQualityCodec,
725 N = RawNameCodec,
726 K = NoRecordKey,
727> {
728 reader: DryIceReader<R, S, Q, N, K>,
729}
730
731impl<R: Read, S: SequenceCodec, Q: QualityCodec, N: NameCodec, K> Iterator
732 for DryIceRecords<R, S, Q, N, K>
733{
734 type Item = Result<SeqRecord, DryIceError>;
735
736 fn next(&mut self) -> Option<Self::Item> {
737 match self.reader.next_record() {
738 Ok(true) => Some(self.reader.to_seq_record()),
739 Ok(false) => None,
740 Err(e) => Some(Err(e)),
741 }
742 }
743}