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.is_empty() {
36 Ok(0)
37 } else if slice.bs.len() <= usize::BITS as usize {
38 Ok(slice.bs.load_le::<usize>())
39 } else {
40 let len: usize = slice.bs.len() / A::BITS as usize;
41 let maximum: usize = usize::BITS as usize / A::BITS as usize;
42 Err(ParseBioError::SequenceTooLong(maximum, len))
43 }
44 }
45}
46
47impl<A: Codec> From<&SeqSlice<A>> for u8 {
48 fn from(slice: &SeqSlice<A>) -> u8 {
49 debug_assert!(slice.bs.len() <= u8::BITS as usize);
50 if slice.bs.is_empty() {
51 0
52 } else {
53 slice.bs.load_le::<u8>()
54 }
55 }
56}
57
58impl<A: Codec> SeqSlice<A> {
59 #[must_use]
61 pub fn nth(&self, i: usize) -> A {
62 A::unsafe_from_bits(self[i].into())
63 }
64
65 #[must_use]
66 pub fn len(&self) -> usize {
67 self.bs.len() / A::BITS as usize
68 }
69
70 #[must_use]
72 pub fn get(&self, i: usize) -> Option<A> {
73 if i >= self.bs.len() / A::BITS as usize {
74 None
75 } else {
76 Some(A::unsafe_from_bits(self[i].into()))
77 }
78 }
79
80 #[must_use]
81 pub fn is_empty(&self) -> bool {
82 self.len() == 0
83 }
84}
85
86impl<A: Codec> From<&SeqSlice<A>> for String {
87 fn from(seq: &SeqSlice<A>) -> Self {
88 seq.into_iter().map(Codec::to_char).collect()
89 }
90}
91
92impl<A: Codec> PartialEq<SeqSlice<A>> for SeqSlice<A> {
93 fn eq(&self, other: &SeqSlice<A>) -> bool {
94 self.bs == other.bs
95 }
96}
97
98impl<A: Codec> PartialEq<SeqSlice<A>> for &SeqSlice<A> {
99 fn eq(&self, other: &SeqSlice<A>) -> bool {
100 self.bs == other.bs
101 }
102}
103
104impl<A: Codec> PartialEq<Seq<A>> for SeqSlice<A> {
105 fn eq(&self, other: &Seq<A>) -> bool {
106 self == other.as_ref()
107 }
108}
109
110impl<A: Codec> PartialEq<Seq<A>> for &SeqSlice<A> {
111 fn eq(&self, other: &Seq<A>) -> bool {
112 *self == other.as_ref()
113 }
114}
115
116impl<A: Codec> PartialEq<&str> for SeqSlice<A> {
117 fn eq(&self, other: &&str) -> bool {
118 let bs = other.as_bytes();
119 if bs.len() != self.len() {
120 return false;
121 }
122 for (a, c) in self.iter().zip(bs) {
123 match A::try_from_ascii(*c) {
124 Some(b) => {
125 if a != b {
126 return false;
127 }
128 }
129 None => return false,
130 }
131 }
132 true
133 }
134}
135
136impl<A: Codec> Hash for SeqSlice<A> {
137 fn hash<H: Hasher>(&self, state: &mut H) {
138 state.write(&(self.len() as u64).to_le_bytes());
143 crate::hash::hash_bits(&self.bs, state);
144 }
145}
146
147impl<A: Codec> ToOwned for SeqSlice<A> {
160 type Owned = Seq<A>;
161
162 fn to_owned(&self) -> Self::Owned {
163 Seq {
164 _p: PhantomData,
165 bv: self.bs.into(),
166 }
167 }
168}
169
170impl<A: Codec> AsRef<SeqSlice<A>> for SeqSlice<A> {
171 fn as_ref(&self) -> &SeqSlice<A> {
172 self
173 }
174}
175
176impl<A: Codec> fmt::Display for SeqSlice<A> {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 for symbol in self {
179 write!(f, "{}", symbol.to_char())?;
180 }
181 Ok(())
182 }
183}
184
185impl<A: Codec> BitAnd for &SeqSlice<A> {
186 type Output = Seq<A>;
187
188 fn bitand(self, rhs: Self) -> Self::Output {
189 let mut bv = self.bs.to_bitvec();
190 bv &= &rhs.bs;
191 Seq::<A> {
192 bv,
193 _p: PhantomData,
194 }
195 }
196}
197
198impl<A: Codec> BitOr for &SeqSlice<A> {
199 type Output = Seq<A>;
200
201 fn bitor(self, rhs: Self) -> Self::Output {
202 let mut bv = self.bs.to_bitvec();
203 bv |= &rhs.bs;
204
205 Seq::<A> {
206 bv,
207 _p: PhantomData,
208 }
209 }
210}
211
212impl<A: Codec> ReverseMut for SeqSlice<A> {
213 fn rev(&mut self) {
214 self.bs.reverse();
215 for chunk in self.bs.rchunks_exact_mut(A::BITS as usize) {
216 chunk.reverse();
217 }
218 }
219}
220
221impl<A: Codec + ComplementMut> ComplementMut for SeqSlice<A> {
222 fn comp(&mut self) {
223 unsafe {
224 for base in self.bs.chunks_exact_mut(A::BITS as usize).remove_alias() {
225 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
226 bc.comp();
227 base.store(bc.to_bits() as usize);
228 }
229 }
230 }
231}
232
233impl<A: Codec + ComplementMut> ReverseComplementMut for SeqSlice<A> where
234 SeqSlice<A>: ComplementMut + ReverseMut
235{
236}
237
238impl<A: Codec> Reverse for SeqSlice<A> {}
239
240impl<A: Codec + ComplementMut> Complement for SeqSlice<A> {}
241
242impl<A: Codec + ComplementMut> ReverseComplement for SeqSlice<A> where
243 SeqSlice<A>: ComplementMut + ReverseMut
244{
245}