1use std::{fs::File, io, path::Path};
7
8pub use angsd_saf::{
9 record::Id,
10 version::{Version, V3, V4},
11 ReadStatus,
12};
13
14use crate::saf::Site;
15
16mod adaptors;
17pub use adaptors::{Enumerate, Take};
18
19pub mod shuffle;
20
21pub trait ReadSite {
23 type Site;
25
26 fn read_site(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus>;
33
34 fn read_site_unnormalised(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus>;
38
39 fn enumerate(self) -> Enumerate<Self>
41 where
42 Self: Sized,
43 {
44 Enumerate::new(self)
45 }
46
47 fn take(self, max_sites: usize) -> Take<Enumerate<Self>>
49 where
50 Self: Sized,
51 {
52 Take::new(Enumerate::new(self), max_sites)
53 }
54}
55
56pub trait Rewind: ReadSite {
58 #[allow(clippy::wrong_self_convention)]
60 fn is_done(&mut self) -> io::Result<bool>;
61
62 fn rewind(&mut self) -> io::Result<()>;
67}
68
69impl<'a, T> Rewind for &'a mut T
70where
71 T: Rewind,
72{
73 fn is_done(&mut self) -> io::Result<bool> {
74 <T as Rewind>::is_done(*self)
75 }
76
77 fn rewind(&mut self) -> io::Result<()> {
78 <T as Rewind>::rewind(*self)
79 }
80}
81
82impl<'a, T> ReadSite for &'a mut T
83where
84 T: ReadSite,
85{
86 type Site = T::Site;
87
88 fn read_site(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
89 <T as ReadSite>::read_site(*self, buf)
90 }
91
92 fn read_site_unnormalised(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
93 <T as ReadSite>::read_site_unnormalised(*self, buf)
94 }
95}
96
97pub struct Intersect<const D: usize, R, V>
102where
103 V: Version,
104{
105 inner: angsd_saf::Intersect<R, V>,
107 bufs: [angsd_saf::Record<Id, V::Item>; D],
108}
109
110impl<const D: usize, R, V> Intersect<D, R, V>
111where
112 R: io::BufRead + io::Seek,
113 V: Version,
114{
115 pub fn get(&self) -> &angsd_saf::Intersect<R, V> {
117 &self.inner
118 }
119
120 pub fn get_mut(&mut self) -> &mut angsd_saf::Intersect<R, V> {
122 &mut self.inner
123 }
124
125 pub fn into_inner(self) -> angsd_saf::Intersect<R, V> {
127 self.inner
128 }
129
130 pub fn new(readers: [angsd_saf::Reader<R, V>; D]) -> Self {
132 let inner = angsd_saf::Intersect::new(readers.into());
133 let bufs = inner
134 .create_record_bufs()
135 .try_into()
136 .map_err(|_| ())
137 .unwrap();
138
139 Self { inner, bufs }
140 }
141}
142
143impl<const D: usize, V> Intersect<D, io::BufReader<File>, V>
144where
145 V: Version,
146{
147 pub fn from_paths<P>(paths: &[P; D]) -> io::Result<Self>
151 where
152 P: AsRef<Path>,
153 {
154 paths
155 .iter()
156 .map(|p| angsd_saf::reader::Builder::<V>::default().build_from_member_path(p))
157 .collect::<io::Result<Vec<_>>>()
158 .map(|vec| Self::new(vec.try_into().map_err(|_| ()).unwrap()))
159 }
160}
161
162impl<const D: usize, R> ReadSite for Intersect<D, R, V3>
163where
164 R: io::BufRead + io::Seek,
165{
166 type Site = Site<D>;
167
168 fn read_site(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
169 let status = self.read_site_unnormalised(buf)?;
170
171 buf.iter_mut().for_each(|x| *x = x.exp());
172
173 Ok(status)
174 }
175
176 fn read_site_unnormalised(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
177 let status = self.inner.read_records(&mut self.bufs)?;
178
179 let src = self.bufs.iter().map(|record| record.item());
180 copy_from_slices(src, buf.as_mut_slice());
181
182 Ok(status)
183 }
184}
185
186impl<const D: usize, R> ReadSite for Intersect<D, R, V4>
187where
188 R: io::BufRead + io::Seek,
189{
190 type Site = Site<D>;
193
194 fn read_site(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
195 let status = self.read_site_unnormalised(buf)?;
196
197 buf.iter_mut().for_each(|x| *x = x.exp());
198
199 Ok(status)
200 }
201
202 fn read_site_unnormalised(&mut self, buf: &mut Self::Site) -> io::Result<ReadStatus> {
203 let status = self.inner.read_records(&mut self.bufs)?;
204
205 let alleles_iter = self
206 .inner
207 .get_readers()
208 .iter()
209 .map(|reader| reader.index().alleles());
210 let src = self
211 .bufs
212 .iter_mut()
213 .zip(alleles_iter)
214 .map(|(record, alleles)| record.item().clone().into_full(alleles, f32::NEG_INFINITY));
215 copy_from_slices(src, buf.as_mut_slice());
216
217 Ok(status)
218 }
219}
220
221fn copy_from_slices<I, T>(src: I, dest: &mut [T])
225where
226 I: IntoIterator,
227 I::Item: AsRef<[T]>,
228 T: Copy,
229{
230 let mut offset = 0;
231 for s in src {
232 let n = s.as_ref().len();
233 dest[offset..][..n].copy_from_slice(s.as_ref());
234 offset += n;
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use super::*;
241
242 #[test]
243 fn test_copy_from_slices() {
244 let src = vec![&[0, 1][..], &[2, 3, 4, 5]];
245 let mut dest = vec![0; 6];
246 copy_from_slices(src, dest.as_mut_slice());
247 assert_eq!(dest, (0..6).collect::<Vec<_>>());
248 }
249}