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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::fmt;
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub enum Operation {
Sentinel = 0u8,
M = 1u8,
I = 2u8,
D = 3u8
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct OpLen {
pub op: Operation,
pub len: usize
}
pub struct Cigar {
s: Vec<OpLen>,
idx: usize
}
impl Cigar {
pub unsafe fn new(max_len: usize) -> Self {
let s = vec![OpLen { op: Operation::Sentinel, len: 0 }; max_len + 1];
let idx = 1;
Cigar { s, idx }
}
pub unsafe fn add(&mut self, op: Operation) {
debug_assert!(self.idx < self.s.len());
let add = (op != (*self.s.as_ptr().add(self.idx - 1)).op) as usize;
self.idx += add;
(*self.s.as_mut_ptr().add(self.idx - 1)).op = op;
(*self.s.as_mut_ptr().add(self.idx - 1)).len += 1;
}
pub fn len(&self) -> usize {
self.idx - 1
}
pub fn get(&self, i: usize) -> OpLen {
self.s[self.idx - 1 - i]
}
pub fn format(&self, q: &[u8], r: &[u8]) -> (String, String) {
let mut a = String::with_capacity(self.s.len());
let mut b = String::with_capacity(self.s.len());
let mut i = 0;
let mut j = 0;
for &op_len in self.s.iter().rev() {
match op_len.op {
Operation::M => {
for _k in 0..op_len.len {
a.push(q[i] as char);
b.push(r[j] as char);
i += 1;
j += 1;
}
},
Operation::I => {
for _k in 0..op_len.len {
a.push(q[i] as char);
b.push('-');
i += 1;
}
},
Operation::D => {
for _k in 0..op_len.len {
a.push('-');
b.push(r[j] as char);
j += 1;
}
},
_ => continue
}
}
(a, b)
}
pub fn to_vec(&self) -> Vec<OpLen> {
self.s
.iter()
.rev()
.filter(|op_len| op_len.op != Operation::Sentinel)
.map(|&op_len| op_len)
.collect::<Vec<OpLen>>()
}
}
impl fmt::Display for Cigar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for &op_len in self.s.iter().rev() {
let c = match op_len.op {
Operation::M => 'M',
Operation::I => 'I',
Operation::D => 'D',
_ => continue
};
write!(f, "{}{}", op_len.len, c)?;
}
Ok(())
}
}