1use crate::codec::Codec;
7use crate::error::ParseBioError;
8use crate::seq::Seq;
9use crate::{
10 Complement, ComplementMut, Reverse, ReverseComplement, ReverseComplementMut, ReverseMut,
11};
12
13use crate::Bs;
14use bitvec::field::BitField;
15
16use core::fmt;
17use core::hash::{Hash, Hasher};
18use core::marker::PhantomData;
19use core::str;
20
21use core::ops::{BitAnd, BitOr};
22
23#[derive(Debug, Eq)]
25#[repr(transparent)]
26pub struct SeqSlice<A: Codec> {
27 pub(crate) _p: PhantomData<A>,
28 pub(crate) bs: Bs,
29}
30
31impl<A: Codec> TryFrom<&SeqSlice<A>> for usize {
32 type Error = ParseBioError;
33
34 fn try_from(slice: &SeqSlice<A>) -> Result<usize, Self::Error> {
35 if slice.bs.len() <= usize::BITS as usize {
36 Ok(slice.bs.load_le::<usize>())
37 } else {
38 let len: usize = slice.bs.len() / A::BITS as usize;
39 let maximum: usize = usize::BITS as usize / A::BITS as usize;
40 Err(ParseBioError::SequenceTooLong(maximum, len))
41 }
42 }
43}
44
45impl<A: Codec> From<&SeqSlice<A>> for u8 {
46 fn from(slice: &SeqSlice<A>) -> u8 {
47 debug_assert!(slice.bs.len() <= u8::BITS as usize);
48 slice.bs.load_le::<u8>()
49 }
50}
51
52impl<A: Codec> SeqSlice<A> {
53 pub fn nth(&self, i: usize) -> A {
55 A::unsafe_from_bits(self[i].into())
56 }
57
58 pub fn len(&self) -> usize {
59 self.bs.len() / A::BITS as usize
60 }
61
62 pub fn get(&self, i: usize) -> Option<A> {
64 if i >= self.bs.len() / A::BITS as usize {
65 None
66 } else {
67 Some(A::unsafe_from_bits(self[i].into()))
68 }
69 }
70
71 pub fn is_empty(&self) -> bool {
72 self.len() == 0
73 }
74}
75
76impl<A: Codec> From<&SeqSlice<A>> for String {
77 fn from(seq: &SeqSlice<A>) -> Self {
78 seq.into_iter().map(Codec::to_char).collect()
79 }
80}
81
82impl<A: Codec> PartialEq<SeqSlice<A>> for SeqSlice<A> {
83 fn eq(&self, other: &SeqSlice<A>) -> bool {
84 self.bs == other.bs
85 }
86}
87
88impl<A: Codec> PartialEq<SeqSlice<A>> for &SeqSlice<A> {
89 fn eq(&self, other: &SeqSlice<A>) -> bool {
90 self.bs == other.bs
91 }
92}
93
94impl<A: Codec> PartialEq<Seq<A>> for SeqSlice<A> {
95 fn eq(&self, other: &Seq<A>) -> bool {
96 self == other.as_ref()
97 }
98}
99
100impl<A: Codec> PartialEq<Seq<A>> for &SeqSlice<A> {
101 fn eq(&self, other: &Seq<A>) -> bool {
102 *self == other.as_ref()
103 }
104}
105
106impl<A: Codec> PartialEq<&str> for SeqSlice<A> {
107 fn eq(&self, other: &&str) -> bool {
108 let bs = other.as_bytes();
109 if bs.len() != self.len() {
110 return false;
111 }
112 for (a, c) in self.iter().zip(bs) {
113 match A::try_from_ascii(*c) {
114 Some(b) => {
115 if a != b {
116 return false;
117 }
118 }
119 None => return false,
120 }
121 }
122 true
123 }
124}
125
126impl<A: Codec> Hash for SeqSlice<A> {
127 fn hash<H: Hasher>(&self, state: &mut H) {
128 state.write(&(self.len() as u64).to_le_bytes());
133 crate::hash::hash_bits(&self.bs, state);
134 }
135}
136
137impl<A: Codec> ToOwned for SeqSlice<A> {
150 type Owned = Seq<A>;
151
152 fn to_owned(&self) -> Self::Owned {
153 Seq {
154 _p: PhantomData,
155 bv: self.bs.into(),
156 }
157 }
158}
159
160impl<A: Codec> AsRef<SeqSlice<A>> for SeqSlice<A> {
161 fn as_ref(&self) -> &SeqSlice<A> {
162 self
163 }
164}
165
166impl<A: Codec> fmt::Display for SeqSlice<A> {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "{}", String::from(self))
169 }
170}
171
172impl<A: Codec> BitAnd for &SeqSlice<A> {
173 type Output = Seq<A>;
174
175 fn bitand(self, rhs: Self) -> Self::Output {
176 let mut bv = self.bs.to_bitvec();
177 bv &= &rhs.bs;
178 Seq::<A> {
179 bv,
180 _p: PhantomData,
181 }
182 }
183}
184
185impl<A: Codec> BitOr for &SeqSlice<A> {
186 type Output = Seq<A>;
187
188 fn bitor(self, rhs: Self) -> Self::Output {
189 let mut bv = self.bs.to_bitvec();
190 bv |= &rhs.bs;
191
192 Seq::<A> {
193 bv,
194 _p: PhantomData,
195 }
196 }
197}
198
199impl<A: Codec> ReverseMut for SeqSlice<A> {
200 fn rev(&mut self) {
201 self.bs.reverse();
202 for chunk in self.bs.rchunks_exact_mut(A::BITS as usize) {
203 chunk.reverse();
204 }
205 }
206}
207
208impl<A: Codec + ComplementMut> ComplementMut for SeqSlice<A> {
209 fn comp(&mut self) {
210 unsafe {
211 for base in self.bs.chunks_exact_mut(A::BITS as usize).remove_alias() {
212 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
213 bc.comp();
214 base.store(bc.to_bits() as usize);
215 }
216 }
217 }
218}
219
220impl<A: Codec + ComplementMut> ReverseComplementMut for SeqSlice<A> where
221 SeqSlice<A>: ComplementMut + ReverseMut
222{
223}
224
225impl<A: Codec> Reverse for SeqSlice<A> {}
226
227impl<A: Codec + ComplementMut> Complement for SeqSlice<A> {}
228
229impl<A: Codec + ComplementMut> ReverseComplement for SeqSlice<A> where
230 SeqSlice<A>: ComplementMut + ReverseMut
231{
232}