noodles_vcf/variant/
record_buf.rs

1//! Variant record buffer.
2
3mod alternate_bases;
4pub mod builder;
5mod convert;
6mod filters;
7pub mod ids;
8pub mod info;
9pub mod samples;
10
11use std::io;
12
13use noodles_core::Position;
14
15pub use self::{
16    alternate_bases::AlternateBases, builder::Builder, filters::Filters, ids::Ids, info::Info,
17    samples::Samples,
18};
19use crate::Header;
20
21/// A variant record buffer.
22#[derive(Clone, Debug, PartialEq)]
23pub struct RecordBuf {
24    reference_sequence_name: String,
25    variant_start: Option<Position>,
26    ids: Ids,
27    reference_bases: String,
28    alternate_bases: AlternateBases,
29    quality_score: Option<f32>,
30    filters: Filters,
31    info: Info,
32    samples: Samples,
33}
34
35impl RecordBuf {
36    /// Returns a builder to create a record from each of its fields.
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// use noodles_vcf as vcf;
42    /// let builder = vcf::variant::RecordBuf::builder();
43    /// ```
44    pub fn builder() -> Builder {
45        Builder::default()
46    }
47
48    /// Returns the reference sequence name.
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// use noodles_vcf as vcf;
54    ///
55    /// let record = vcf::variant::RecordBuf::builder()
56    ///     .set_reference_sequence_name("sq0")
57    ///     .build();
58    ///
59    /// assert_eq!(record.reference_sequence_name(), "sq0");
60    /// ```
61    pub fn reference_sequence_name(&self) -> &str {
62        &self.reference_sequence_name
63    }
64
65    /// Returns a mutable reference to the reference sequence name.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use noodles_vcf as vcf;
71    ///
72    /// let mut record = vcf::variant::RecordBuf::builder()
73    ///     .set_reference_sequence_name("sq0")
74    ///     .build();
75    ///
76    /// *record.reference_sequence_name_mut() = String::from("sq1");
77    ///
78    /// assert_eq!(record.reference_sequence_name(), "sq1");
79    /// ```
80    pub fn reference_sequence_name_mut(&mut self) -> &mut String {
81        &mut self.reference_sequence_name
82    }
83
84    /// Returns the variant start position.
85    ///
86    /// This position is 1-based, inclusive. If the record represents the start of a telomeric
87    /// breakend, this returns `None`.
88    ///
89    /// # Examples
90    ///
91    /// ```
92    /// use noodles_core::Position;
93    /// use noodles_vcf as vcf;
94    ///
95    /// let record = vcf::variant::RecordBuf::builder()
96    ///     .set_variant_start(Position::MIN)
97    ///     .build();
98    ///
99    /// assert_eq!(record.variant_start(), Some(Position::MIN));
100    /// ```
101    pub fn variant_start(&self) -> Option<Position> {
102        self.variant_start
103    }
104
105    /// Returns a mutable reference to the variant start position.
106    ///
107    /// This position is 1-based, inclusive. If the record represents the start of a telomeric
108    /// breakend, this returns `None`.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use noodles_core::Position;
114    /// use noodles_vcf as vcf;
115    ///
116    /// let mut record = vcf::variant::RecordBuf::default();
117    /// *record.variant_start_mut() = Some(Position::MIN);
118    /// assert_eq!(record.variant_start(), Some(Position::MIN));
119    /// ```
120    pub fn variant_start_mut(&mut self) -> &mut Option<Position> {
121        &mut self.variant_start
122    }
123
124    /// Returns a list of IDs of the record.
125    ///
126    /// # Examples
127    ///
128    /// ```
129    /// use noodles_vcf::{self as vcf, variant::record_buf::Ids};
130    ///
131    /// let ids: Ids = [String::from("nd0")].into_iter().collect();
132    ///
133    /// let record = vcf::variant::RecordBuf::builder()
134    ///     .set_ids(ids.clone())
135    ///     .build();
136    ///
137    /// assert_eq!(record.ids(), &ids);
138    /// ```
139    pub fn ids(&self) -> &Ids {
140        &self.ids
141    }
142
143    /// Returns a mutable reference to the IDs.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use noodles_vcf::{self as vcf, variant::record_buf::Ids};
149    ///
150    /// let mut record = vcf::variant::RecordBuf::default();
151    ///
152    /// let ids: Ids = [String::from("nd0")].into_iter().collect();
153    /// *record.ids_mut() = ids.clone();
154    ///
155    /// assert_eq!(record.ids(), &ids);
156    /// ```
157    pub fn ids_mut(&mut self) -> &mut Ids {
158        &mut self.ids
159    }
160
161    /// Returns the reference bases of the record.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use noodles_vcf as vcf;
167    ///
168    /// let record = vcf::variant::RecordBuf::builder()
169    ///     .set_reference_bases("A")
170    ///     .build();
171    ///
172    /// assert_eq!(record.reference_bases(), "A");
173    /// ```
174    pub fn reference_bases(&self) -> &str {
175        &self.reference_bases
176    }
177
178    /// Returns a mutable reference to the reference bases of the record.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// use noodles_vcf as vcf;
184    ///
185    /// let mut record = vcf::variant::RecordBuf::builder()
186    ///     .set_reference_bases("A")
187    ///     .build();
188    ///
189    /// *record.reference_bases_mut() = String::from("T");
190    ///
191    /// assert_eq!(record.reference_bases(), "T");
192    /// ```
193    pub fn reference_bases_mut(&mut self) -> &mut String {
194        &mut self.reference_bases
195    }
196
197    /// Returns the alternate bases of the record.
198    ///
199    /// # Examples
200    ///
201    /// ```
202    /// use noodles_vcf::{self as vcf, variant::record_buf::AlternateBases};
203    ///
204    /// let alternate_bases = AlternateBases::from(vec![String::from("C")]);
205    ///
206    /// let record = vcf::variant::RecordBuf::builder()
207    ///     .set_alternate_bases(alternate_bases.clone())
208    ///     .build();
209    ///
210    /// assert_eq!(record.alternate_bases(), &alternate_bases);
211    /// ```
212    pub fn alternate_bases(&self) -> &AlternateBases {
213        &self.alternate_bases
214    }
215
216    /// Returns a mutable reference to the alternate bases of the record.
217    ///
218    /// # Examples
219    ///
220    /// ```
221    /// use noodles_vcf::{self as vcf, variant::record_buf::AlternateBases};
222    ///
223    /// let mut record = vcf::variant::RecordBuf::builder()
224    ///     .set_reference_bases("A")
225    ///     .build();
226    ///
227    /// let alternate_bases = AlternateBases::from(vec![String::from("C")]);
228    /// *record.alternate_bases_mut() = alternate_bases.clone();
229    ///
230    /// assert_eq!(record.alternate_bases(), &alternate_bases);
231    /// ```
232    pub fn alternate_bases_mut(&mut self) -> &mut AlternateBases {
233        &mut self.alternate_bases
234    }
235
236    /// Returns the quality score of the record.
237    ///
238    /// # Examples
239    ///
240    /// ```
241    /// use noodles_vcf as vcf;
242    ///
243    /// let record = vcf::variant::RecordBuf::builder()
244    ///     .set_quality_score(13.0)
245    ///     .build();
246    ///
247    /// assert_eq!(record.quality_score(), Some(13.0));
248    /// ```
249    pub fn quality_score(&self) -> Option<f32> {
250        self.quality_score
251    }
252
253    /// Returns a mutable reference to the quality score.
254    ///
255    /// # Examples
256    ///
257    /// ```
258    /// use noodles_vcf as vcf;
259    ///
260    /// let mut record = vcf::variant::RecordBuf::default();
261    /// *record.quality_score_mut() = Some(13.0);
262    /// assert_eq!(record.quality_score(), Some(13.0));
263    /// ```
264    pub fn quality_score_mut(&mut self) -> &mut Option<f32> {
265        &mut self.quality_score
266    }
267
268    /// Returns the filters of the record.
269    ///
270    /// The filters can either be pass (`PASS`), a list of filter names that caused the record to
271    /// fail, (e.g., `q10`), or missing (`.`).
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// use noodles_vcf::{self as vcf, variant::record_buf::Filters};
277    ///
278    /// let record = vcf::variant::RecordBuf::builder()
279    ///     .set_filters(Filters::pass())
280    ///     .build();
281    ///
282    /// assert!(record.filters().is_pass());
283    /// ```
284    pub fn filters(&self) -> &Filters {
285        &self.filters
286    }
287
288    /// Returns a mutable reference to the filters.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// use noodles_vcf::{self as vcf, variant::record_buf::Filters};
294    ///
295    /// let mut record = vcf::variant::RecordBuf::default();
296    /// *record.filters_mut() = Filters::pass();
297    /// assert!(record.filters().is_pass());
298    /// ```
299    pub fn filters_mut(&mut self) -> &mut Filters {
300        &mut self.filters
301    }
302
303    /// Returns the addition information of the record.
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// use noodles_vcf::{
309    ///     self as vcf,
310    ///     variant::{
311    ///         record::info::field::key,
312    ///         record_buf::{info::field::Value, Info},
313    ///     },
314    /// };
315    ///
316    /// let info: Info = [
317    ///     (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::from(3))),
318    ///     (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
319    /// ]
320    /// .into_iter()
321    /// .collect();
322    ///
323    /// let record = vcf::variant::RecordBuf::builder()
324    ///     .set_info(info.clone())
325    ///     .build();
326    ///
327    /// assert_eq!(record.info(), &info);
328    /// ```
329    pub fn info(&self) -> &Info {
330        &self.info
331    }
332
333    /// Returns a mutable reference to the additional info fields.
334    ///
335    /// # Examples
336    ///
337    /// ```
338    /// use noodles_vcf::{
339    ///     self as vcf,
340    ///     variant::{
341    ///         record::info::field::key,
342    ///         record_buf::{info::field::Value, Info},
343    ///     }
344    /// };
345    ///
346    /// let info: Info = [
347    ///     (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::from(3))),
348    ///     (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
349    /// ]
350    /// .into_iter()
351    /// .collect();
352    ///
353    /// let mut record = vcf::variant::RecordBuf::builder()
354    ///     .set_info(info)
355    ///     .build();
356    ///
357    /// record.info_mut().insert(String::from(key::TOTAL_DEPTH), Some(Value::Integer(13)));
358    ///
359    /// let expected = [
360    ///     (String::from(key::SAMPLES_WITH_DATA_COUNT), Some(Value::Integer(3))),
361    ///     (String::from(key::ALLELE_FREQUENCIES), Some(Value::from(vec![Some(0.5)]))),
362    ///     (String::from(key::TOTAL_DEPTH), Some(Value::Integer(13))),
363    /// ]
364    /// .into_iter()
365    /// .collect();
366    ///
367    /// assert_eq!(record.info(), &expected);
368    /// ```
369    pub fn info_mut(&mut self) -> &mut Info {
370        &mut self.info
371    }
372
373    /// Returns the format of the genotypes of the record.
374    ///
375    /// # Examples
376    ///
377    /// ```
378    /// use noodles_vcf::{
379    ///     self as vcf,
380    ///     variant::{
381    ///         record::samples::keys::key,
382    ///         record_buf::{samples::{sample::Value, Keys}, Samples},
383    ///     },
384    /// };
385    ///
386    /// let keys: Keys = [
387    ///     String::from(key::GENOTYPE),
388    ///     String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
389    /// ].into_iter().collect();
390    /// let samples = Samples::new(
391    ///     keys.clone(),
392    ///     vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
393    /// );
394    ///
395    /// let record = vcf::variant::RecordBuf::builder()
396    ///     .set_samples(samples)
397    ///     .build();
398    ///
399    /// assert_eq!(record.format(), &keys);
400    /// ```
401    pub fn format(&self) -> &samples::Keys {
402        self.samples.keys()
403    }
404
405    /// Returns the genotypes of the record.
406    ///
407    /// # Examples
408    ///
409    /// ```
410    /// use noodles_vcf::{
411    ///     self as vcf,
412    ///     variant::{
413    ///         record::samples::keys::key,
414    ///         record_buf::{samples::sample::Value, Samples},
415    ///     },
416    /// };
417    ///
418    /// let keys = [
419    ///     String::from(key::GENOTYPE),
420    ///     String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
421    /// ].into_iter().collect();
422    /// let samples = Samples::new(
423    ///     keys,
424    ///     vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
425    /// );
426    ///
427    /// let record = vcf::variant::RecordBuf::builder()
428    ///     .set_samples(samples.clone())
429    ///     .build();
430    ///
431    /// assert_eq!(record.samples(), &samples);
432    /// ```
433    pub fn samples(&self) -> &Samples {
434        &self.samples
435    }
436
437    /// Returns a mutable reference to the genotypes of the record.
438    ///
439    /// # Examples
440    ///
441    /// ```
442    /// use noodles_vcf::{
443    ///     self as vcf,
444    ///     variant::{
445    ///         record::samples::keys::key,
446    ///         record_buf::{samples::sample::Value, Samples},
447    ///     },
448    /// };
449    ///
450    /// let mut record = vcf::variant::RecordBuf::default();
451    ///
452    /// let keys = [
453    ///     String::from(key::GENOTYPE),
454    ///     String::from(key::CONDITIONAL_GENOTYPE_QUALITY),
455    /// ].into_iter().collect();
456    /// let samples = Samples::new(
457    ///     keys,
458    ///     vec![vec![Some(Value::from("0|0")), Some(Value::from(13))]],
459    /// );
460    ///
461    /// *record.samples_mut() = samples.clone();
462    ///
463    /// assert_eq!(record.samples(), &samples);
464    /// ```
465    pub fn samples_mut(&mut self) -> &mut Samples {
466        &mut self.samples
467    }
468}
469
470impl Default for RecordBuf {
471    fn default() -> Self {
472        Self {
473            reference_sequence_name: String::from("."),
474            variant_start: Some(Position::MIN),
475            ids: Ids::default(),
476            reference_bases: String::from("N"),
477            alternate_bases: AlternateBases::default(),
478            quality_score: None,
479            filters: Filters::default(),
480            info: Info::default(),
481            samples: Samples::default(),
482        }
483    }
484}
485
486impl super::Record for RecordBuf {
487    fn reference_sequence_name<'a, 'h: 'a>(&'a self, _: &'h Header) -> io::Result<&'a str> {
488        Ok(self.reference_sequence_name())
489    }
490
491    fn variant_start(&self) -> Option<std::io::Result<Position>> {
492        self.variant_start().map(Ok)
493    }
494
495    fn ids(&self) -> Box<dyn super::record::Ids + '_> {
496        Box::new(self.ids())
497    }
498
499    fn reference_bases(&self) -> Box<dyn super::record::ReferenceBases + '_> {
500        Box::new(self.reference_bases())
501    }
502
503    fn alternate_bases(&self) -> Box<dyn super::record::AlternateBases + '_> {
504        Box::new(self.alternate_bases())
505    }
506
507    fn quality_score(&self) -> Option<std::io::Result<f32>> {
508        self.quality_score().map(Ok)
509    }
510
511    fn filters(&self) -> Box<dyn super::record::Filters + '_> {
512        Box::new(self.filters())
513    }
514
515    fn info(&self) -> Box<dyn super::record::Info + '_> {
516        Box::new(self.info())
517    }
518
519    fn samples(&self) -> io::Result<Box<dyn super::record::Samples + '_>> {
520        Ok(Box::new(self.samples()))
521    }
522}
523
524#[cfg(test)]
525mod tests {
526    use super::*;
527
528    #[test]
529    fn test_default() -> Result<(), Box<dyn std::error::Error>> {
530        let actual = RecordBuf::default();
531
532        let expected = RecordBuf::builder()
533            .set_reference_sequence_name(".")
534            .set_variant_start(Position::MIN)
535            .set_reference_bases("N")
536            .build();
537
538        assert_eq!(actual, expected);
539
540        Ok(())
541    }
542}