1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use super::Alignment;
use super::Nucleotide;

use std::ops::Index;

pub struct Sequence<'a> {
    alignment: &'a Alignment<'a>,
}

impl<'a> Sequence<'a> {
    pub fn len(&self) -> usize {
        self.alignment.seq_len() as usize
    }
    fn read_numeric(&self, offset: usize) -> u32 {
        let hts_obj = self.alignment.hts_obj();
        let seq = unsafe {
            hts_obj.data.offset(
                hts_obj.core.n_cigar as isize * 4
                    + (hts_obj.core.l_qname as isize)
                    + offset as isize / 2,
            )
        };
        let numeric: u32 = if offset % 2 == 0 {
            (unsafe { *seq } as u32) >> 4
        } else {
            (unsafe { *seq } as u32) & 0xf
        };
        return numeric;
    }
}

impl<'a> Index<usize> for Sequence<'a> {
    type Output = Nucleotide;
    fn index(&self, offset: usize) -> &Nucleotide {
        self.read_numeric(offset).into()
    }
}

impl<'a> IntoIterator for Sequence<'a> {
    type Item = Nucleotide;
    type IntoIter = SequenceIter<'a>;
    fn into_iter(self) -> SequenceIter<'a> {
        SequenceIter { seq: self, ofs: 0 }
    }
}

pub struct SequenceIter<'a> {
    seq: Sequence<'a>,
    ofs: usize,
}

impl<'a> Iterator for SequenceIter<'a> {
    type Item = Nucleotide;
    fn next(&mut self) -> Option<Nucleotide> {
        if self.ofs < self.seq.len() {
            let ret = self.seq.read_numeric(self.ofs).into();
            self.ofs += 1;
            return Some(ret);
        }
        None
    }
}

impl<'a> Alignment<'a> {
    pub fn sequence(&self) -> Sequence {
        Sequence { alignment: self }
    }
}