noodles_bcf/record/
samples.rs1mod sample;
4pub mod series;
5
6use std::{io, iter};
7
8use noodles_vcf as vcf;
9
10use self::series::read_series;
11pub use self::{sample::Sample, series::Series};
12
13#[derive(Clone, Debug, Default, Eq, PartialEq)]
15pub struct Samples<'r> {
16 src: &'r [u8],
17 sample_count: usize,
18 format_count: usize,
19}
20
21impl<'r> Samples<'r> {
22 pub(super) fn new(src: &'r [u8], sample_count: usize, format_count: usize) -> Self {
23 Self {
24 src,
25 sample_count,
26 format_count,
27 }
28 }
29
30 pub fn format_count(&self) -> usize {
40 self.format_count
41 }
42
43 pub fn get(&'r self, header: &vcf::Header, sample_name: &str) -> Option<Sample<'r>> {
45 header
46 .sample_names()
47 .get_index_of(sample_name)
48 .and_then(|i| self.get_index(i))
49 }
50
51 pub fn get_index(&'r self, i: usize) -> Option<Sample<'r>> {
53 if i < self.sample_count {
54 Some(Sample::new(self, i))
55 } else {
56 None
57 }
58 }
59
60 pub fn select<'h: 'r>(
62 &'r self,
63 header: &'h vcf::Header,
64 column_name: &str,
65 ) -> Option<io::Result<Series<'r>>> {
66 for result in self.series() {
67 let series = match result {
68 Ok(s) => s,
69 Err(e) => return Some(Err(e)),
70 };
71
72 match series.name(header) {
73 Ok(name) if name == column_name => return Some(Ok(series)),
74 Ok(_) => {}
75 Err(e) => return Some(Err(e)),
76 }
77 }
78
79 None
80 }
81
82 pub fn series(&'r self) -> impl Iterator<Item = io::Result<Series<'r>>> + 'r {
84 let mut src = self.src;
85
86 iter::from_fn(move || {
87 if src.is_empty() {
88 None
89 } else {
90 Some(read_series(&mut src, self.sample_count))
91 }
92 })
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = Sample<'_>> {
97 (0..self.sample_count).map(|i| Sample::new(self, i))
98 }
99}
100
101impl AsRef<[u8]> for Samples<'_> {
102 fn as_ref(&self) -> &[u8] {
103 self.src
104 }
105}
106
107impl vcf::variant::record::Samples for Samples<'_> {
108 fn is_empty(&self) -> bool {
109 self.len() == 0
110 }
111
112 fn len(&self) -> usize {
113 self.sample_count
114 }
115
116 fn column_names<'a, 'h: 'a>(
117 &'a self,
118 header: &'h vcf::Header,
119 ) -> Box<dyn Iterator<Item = io::Result<&'a str>> + 'a> {
120 Box::new(
121 self.series()
122 .map(|result| result.and_then(|series| series.name(header))),
123 )
124 }
125
126 fn select<'a, 'h: 'a>(
127 &'a self,
128 header: &'h vcf::Header,
129 column_name: &str,
130 ) -> Option<io::Result<Box<dyn vcf::variant::record::samples::Series + 'a>>> {
131 self.select(header, column_name).map(|result| {
132 result.map(|series| Box::new(series) as Box<dyn vcf::variant::record::samples::Series>)
133 })
134 }
135
136 fn series(
137 &self,
138 ) -> Box<
139 dyn Iterator<Item = io::Result<Box<dyn vcf::variant::record::samples::Series + '_>>> + '_,
140 > {
141 Box::new(self.series().map(|result| {
142 result.map(|series| Box::new(series) as Box<dyn vcf::variant::record::samples::Series>)
143 }))
144 }
145
146 fn iter(
147 &self,
148 ) -> Box<dyn Iterator<Item = Box<dyn vcf::variant::record::samples::Sample + '_>> + '_> {
149 Box::new(
150 self.iter()
151 .map(|sample| Box::new(sample) as Box<dyn vcf::variant::record::samples::Sample>),
152 )
153 }
154}